diff options
97 files changed, 8286 insertions, 0 deletions
diff --git a/java/gjt/Assert.java b/java/gjt/Assert.java new file mode 100644 index 00000000000..b11f2ec4add --- /dev/null +++ b/java/gjt/Assert.java @@ -0,0 +1,33 @@ +package gjt; + +/** + * A simple assertion mechanism for asserting validity of + * arguments.<p> + * + * @version 1.0, Apr 1 1996 + * @author David Geary + */ +class Assert { + static public void notFalse(boolean b) + throws IllegalArgumentException { + if(b == false) + throw new IllegalArgumentException( + "boolean expression false"); + } + static public void notNull(Object obj) + throws IllegalArgumentException { + if(obj == null) + throw new IllegalArgumentException("null argument"); + } + + static public void notFalse(boolean b, String s) + throws IllegalArgumentException { + if(b == false) + throw new IllegalArgumentException(s); + } + static public void notNull(Object obj, String s) + throws IllegalArgumentException { + if(obj == null) + throw new IllegalArgumentException(s); + } +} diff --git a/java/gjt/Bargauge.java b/java/gjt/Bargauge.java new file mode 100644 index 00000000000..27be8afad7b --- /dev/null +++ b/java/gjt/Bargauge.java @@ -0,0 +1,80 @@ +package gjt; + +import java.awt.*; + +/** + * A bargauge which can be filled (wholly or partially) with a + * client-specified color. Fill color is specified at + * construction time; both fill color and fill percent may be + * set after construction time.<p> + * + * @version 1.0, Apr 1 1996 + * @author David Geary + * @see ThreeDRectangle + * @see gjt.test.BargaugeTest + */ +public class Bargauge extends Canvas { + private double percentFill = 0; + private ThreeDRectangle border = new ThreeDRectangle(this); + private Color fillColor; + + public Bargauge(Color fillColor) { + setFillColor(fillColor); + } + public void setFillColor(Color fillColor) { + this.fillColor = fillColor; + } + public void setFillPercent(double percentage) { + Assert.notFalse(percentage >= 0 && percentage <= 100); + percentFill = percentage; + } + public void resize(int w, int h) { + reshape(location().x, location().y, w, h); + } + public void reshape(int x, int y, int w, int h) { + super.reshape(x,y,w,h); + border.resize(w,h); + } + public Dimension minimumSize() { return preferredSize(); } + + public Dimension preferredSize() { + int w = border.getThickness() * 3; + return new Dimension(w, w*4); + } + public void paint(Graphics g) { + border.raise(); + border.paint(); + fill(); + } + public void fill() { + Graphics g = getGraphics(); + + if((g != null) && (percentFill > 0)) { + Rectangle b = border.getInnerBounds(); + int fillw = b.width; + int fillh = b.height; + + if(b.width > b.height) fillw *= percentFill/100; + else fillh *= percentFill/100; + + g.setColor(fillColor); + border.clearInterior(); + + if(b.width > b.height) + g.fillRect(b.x, b.y, fillw, b.height); + else + g.fillRect(b.x, b.y + b.height - fillh, + b.width, fillh); + } + } + protected String paramString() { + Dimension size = size(); + Orientation orient = size.width > size.height ? + Orientation.HORIZONTAL : + Orientation.VERTICAL; + String str = "fill percent=" + percentFill + "," + + "orientation=" + orient + "," + + "color" + fillColor; + return str; + } +} diff --git a/java/gjt/Border.java b/java/gjt/Border.java new file mode 100644 index 00000000000..ba80ef2e76a --- /dev/null +++ b/java/gjt/Border.java @@ -0,0 +1,105 @@ +package gjt; + +import java.awt.*; + +/** + * A panel containing a single component, around which a border + * is drawn. Of course, the single component may be a + * container which may contain other components, so a Border + * can surround multiple components.<p> + * + * Thickness of the border, and the gap between the Component + * and the border are specified at time of construction. + * Default border thickness is 2 - default gap is 0.<p> + * + * Border color may be set via setLineColor(Color).<p> + * + * Border employs a DrawnRectangle to paint the border. Derived + * classes are free to override DrawnRectangle border() if they + * wish to use an extension of DrawnRectangle for drawing their + * border.<p> + * + * The following code snippet, from gjt.test.BorderTest creates + * and AWT Button, and embeds the button in a border. That + * border is then embedded in another border. The AWT Button + * winds up inside of a cyan border with a pixel width of 7, + * inside of a black border (pixel width 2):<p> + * + * <pre> + * private Border makeBorderedAWTButton() { + * Button button; + * Border cyanBorder, blackBorder; + * + * button = new Button("Button Inside Two Borders"); + * cyanBorder = new Border(button, 7); + * cyanBorder.setLineColor(Color.cyan); + * + * blackBorder = new Border(cyanBorder); + * + * return blackBorder; + * } + *</pre> + * + * @version 1.0, Apr 1 1996 + * @author David Geary + * @see DrawnRectangle + * @see ThreeDBorder + * @see EtchedBorder + * @see gjt.test.BorderTest + */ +public class Border extends Panel { + protected int thickness; + protected int gap; + protected DrawnRectangle border; + + protected static int _defaultThickness = 2; + protected static int _defaultGap = 0; + + public Border(Component borderMe) { + this(borderMe, _defaultThickness, _defaultGap); + } + public Border(Component borderMe, int thickness) { + this(borderMe, thickness, _defaultGap); + } + public Border(Component borderMe, int thickness, int gap) { + this.thickness = thickness; + this.gap = gap; + + setLayout(new BorderLayout()); + add("Center", borderMe); + } + public Insets insets() { + return new Insets(thickness+gap, thickness+gap, + thickness+gap, thickness+gap); + } + public Rectangle getInnerBounds() { + return border().getInnerBounds(); + } + public void setLineColor(Color c) { + border().setLineColor(c); + } + public Color getLineColor() { + return border().getLineColor(); + } + public void paint(Graphics g) { + border().paint(); + } + public void resize(int w, int h) { + Point location = location(); + reshape(location.x, location.y, w, h); + } + public void reshape(int x, int y, int w, int h) { + super.reshape(x, y, w, h); + border().resize(w, h); + } + protected String paramString() { + return super.paramString() + ",border=" + + border().toString() + ",thickness=" + thickness + + ",gap=" + gap; + } + protected DrawnRectangle border() { + if(border == null) + border = new DrawnRectangle(this, thickness); + return border; + } +} diff --git a/java/gjt/Box.java b/java/gjt/Box.java new file mode 100644 index 00000000000..8feda366942 --- /dev/null +++ b/java/gjt/Box.java @@ -0,0 +1,81 @@ +package gjt; + +import java.awt.*; + +/** + * A Panel containing a single component; an etched rectangle is + * drawn around the component, and a Label is centered at the top + * of the rectangle. Of course, the single component may be + * a container, and therefore a Box may surround many components. + * <p> + * + * Both the Component around which the box is drawn, and the + * String drawn at the top of the box are specified at + * construction time.<p> + * + * Etching of the box is controlled by etchedIn() and + * etchedOut(). Default etching is etched in.<p> + * + * <em>Note: AWT 1.0.2 contains a bug which causes the + * Label.CENTER argument of the Label created for the title + * to be ignored, under Win95. Therefore, under Win95, the + * title will be off-center.</em><p> + * + * @version 1.0, Apr 1 1996 + * @author David Geary + * @see EtchedRectangle + * @see gjt.test.BoxTest + */ +public class Box extends Panel { + private EtchedRectangle box = new EtchedRectangle(this); + private Label titleLabel; + + public Box(Component surrounded, String title) { + this(surrounded, new Label(title, Label.CENTER)); + } + public Box(Component surrounded, Label label) { + Assert.notNull(surrounded); + Assert.notNull(label); + + titleLabel = label; + + GridBagLayout gbl = new GridBagLayout(); + GridBagConstraints gbc = new GridBagConstraints(); + + setLayout(gbl); + gbc.gridwidth = GridBagConstraints.REMAINDER; + gbc.anchor = GridBagConstraints.NORTH; + gbl.setConstraints(titleLabel, gbc); + add(titleLabel); + + gbc.insets = new Insets(0,10,10,10); + gbc.anchor = GridBagConstraints.CENTER; + gbc.weighty = 1.0; + gbc.weightx = 1.0; + gbc.fill = GridBagConstraints.BOTH; + gbl.setConstraints(surrounded,gbc); + add(surrounded); + } + public void etchedIn () { box.etchedIn (); } + public void etchedOut() { box.etchedOut(); } + public void paint (Graphics g) { box.paint(); } + + public void resize(int w, int h) { + reshape(location().x, location().y, w, h); + } + public void reshape(int x, int y, int w, int h) { + super.reshape(x,y,w,h); + + FontMetrics fm = titleLabel.getFontMetrics( + titleLabel.getFont()); + int top = insets().top + fm.getAscent(); + Dimension size = size(); + + box.reshape(0, top, size.width-1, size.height-top-1); + } + protected String paramString() { + return super.paramString() + ",etching=" + + (box.isEtchedIn() ? Etching.IN : Etching.OUT) + + ",title=" + titleLabel; + } +} diff --git a/java/gjt/BulletinLayout.java b/java/gjt/BulletinLayout.java new file mode 100644 index 00000000000..848a280de03 --- /dev/null +++ b/java/gjt/BulletinLayout.java @@ -0,0 +1,100 @@ +package gjt; + +import java.awt.*; + +/** + * Lays out components as though they were pinned to + * a bulletin board.<p> + * + * Components are simply reshaped to their location and their + * preferred size. BulletinLayout is preferrable to setting + * a container's layout manager to null and explicitly positioning + * and sizing components.<p> + * + * @version 1.0, Apr 1 1996 + * @author David Geary + */ +public class BulletinLayout implements LayoutManager { + public BulletinLayout() { + } + public void addLayoutComponent(String name, Component comp) { + } + public void removeLayoutComponent(Component comp) { + } + public Dimension preferredLayoutSize(Container target) { + Insets insets = target.insets(); + Dimension dim = new Dimension(0,0); + int ncomponents = target.countComponents(); + Component comp; + Dimension d; + Rectangle preferredBounds = new Rectangle(0,0); + Rectangle compPreferredBounds; + + for (int i = 0 ; i < ncomponents ; i++) { + comp = target.getComponent(i); + + if(comp.isVisible()) { + d = comp.preferredSize(); + compPreferredBounds = + new Rectangle(comp.location()); + compPreferredBounds.width = d.width; + compPreferredBounds.height = d.height; + + preferredBounds = + preferredBounds.union(compPreferredBounds); + } + } + dim.width += insets.left + insets.right; + dim.height += insets.top + insets.bottom; + + return dim; + } + public Dimension minimumLayoutSize(Container target) { + Insets insets = target.insets(); + Dimension dim = new Dimension(0,0); + int ncomponents = target.countComponents(); + Component comp; + Dimension d; + Rectangle minimumBounds = new Rectangle(0,0); + Rectangle compMinimumBounds; + + for (int i = 0 ; i < ncomponents ; i++) { + comp = target.getComponent(i); + + if(comp.isVisible()) { + d = comp.minimumSize(); + compMinimumBounds = + new Rectangle(comp.location()); + compMinimumBounds.width = d.width; + compMinimumBounds.height = d.height; + + minimumBounds = + minimumBounds.union(compMinimumBounds); + } + } + dim.width += insets.left + insets.right; + dim.height += insets.top + insets.bottom; + + return dim; + } + public void layoutContainer(Container target) { + Insets insets = target.insets(); + int ncomponents = target.countComponents(); + Component comp; + Dimension ps; + Point loc; + + for (int i = 0 ; i < ncomponents ; i++) { + comp = target.getComponent(i); + + if(comp.isVisible()) { + ps = comp.preferredSize(); + loc = comp.location(); + + comp.reshape(insets.left + loc.x, + insets.top + loc.y, + ps.width, ps.height); + } + } + } +} diff --git a/java/gjt/ButtonPanel.java b/java/gjt/ButtonPanel.java new file mode 100644 index 00000000000..6fc72ecaab2 --- /dev/null +++ b/java/gjt/ButtonPanel.java @@ -0,0 +1,51 @@ +package gjt; + +import java.awt.*; + +/** + * Button panel employs a BorderLayout to lay out a Separator in + * the north, and a Panel to which Buttons are added in the + * center.<p> + * + * Buttons may be added to the panel via two methods: + * <dl> + * <dd> void add(Button) + * <dd> Button add(String) + * </dl> + * <p> + * + * Button add(String) creates a Button and adds it to the + * panel, then returns the Button created, as a convenience to + * clients so that they do not have to go through the pain + * and agony of creating an ImageButton.<p> + * + * @version 1.0, Apr 1 1996 + * @author David Geary + * @see MessageDialog + * @see QuestionDialog + * @see YesNoDialog + * @see gjt.test.DialogTest + * @see gjt.test.ComponentScrollerTest + */ +public class ButtonPanel extends Panel { + Panel buttonPanel = new Panel(); + Separator separator = new Separator(); + + public ButtonPanel() { + setLayout(new BorderLayout(0,5)); + add("North", separator); + add("Center", buttonPanel); + } + public void add(Button button) { + buttonPanel.add(button); + } + public Button add(String buttonLabel) { + Button addMe = new Button(buttonLabel); + buttonPanel.add(addMe); + return addMe; + } + protected String paramString() { + return super.paramString() + "buttons=" + + countComponents(); + } +} diff --git a/java/gjt/CardPanel.java b/java/gjt/CardPanel.java new file mode 100644 index 00000000000..c2ab1a9033c --- /dev/null +++ b/java/gjt/CardPanel.java @@ -0,0 +1,48 @@ +package gjt; + +import java.awt.*; + +/** + * CardPanel employs a BorderLayout to lay out North and Center + * panels; extensions of CardPanel must implement + * Component viewSelector(). The component returned from + * Component viewSelector() is centered in the North panel, and + * should contain UI controls that allow selection of the + * component to be displayed in the Center panel.<p> + * + * @version 1.0, Apr 1 1996 + * @author David Geary + * @see IconCardPanel + * @see ChoiceCardPanel + * @see gjt.test.ChoiceCardPanelTest + * @see gjt.test.IconCardPanelTest + */ +public abstract class CardPanel extends Panel { + private Panel north, center; + private CardLayout cards; + + abstract public Component viewSelector(); + + public CardPanel() { + center = new Panel(); + north = new Panel(); + + setLayout(new BorderLayout()); + center.setLayout(cards = new CardLayout()); + north.setLayout (new BorderLayout()); + + add("North", north); + add("Center", center); + } + public void addNotify() { + super.addNotify(); + north.add("Center", viewSelector()); + north.add("South", new Separator()); + } + protected void addView(String name, Component component) { + center.add(name, component); + } + protected void showView(String name) { + cards.show(center, name); + } +} diff --git a/java/gjt/ChoiceCardPanel.java b/java/gjt/ChoiceCardPanel.java new file mode 100644 index 00000000000..6273e03a5aa --- /dev/null +++ b/java/gjt/ChoiceCardPanel.java @@ -0,0 +1,53 @@ +package gjt; + +import java.awt.*; + +/** + * ChoiceCardPanel is an extension of CardPanel which presents + * an awt.Choice for selecting the panel to be displayed + * in the center panel.<p> + * + * @version 1.0, Apr 1 1996 + * @author David Geary + * @see CardPanel + * @see IconCardPanel + * @see gjt.test.IconCardPanelTest + * @see gjt.test.ChoiceCardPanelTest + */ +public class ChoiceCardPanel extends CardPanel { + private ChoiceViewSelector viewSelector; + + public ChoiceCardPanel() { + viewSelector = new ChoiceViewSelector(this); + } + public Component viewSelector() { + return viewSelector; + } + public void addChoice(String name, + Component component) { + viewSelector.addItem(name); + super.addView(name, component); + } +} + +class ChoiceViewSelector extends Panel { + private ChoiceCardPanel mvp; + private Choice choice; + + public ChoiceViewSelector(ChoiceCardPanel panel) { + setLayout(new FlowLayout()); + add(choice = new Choice()); + mvp = panel; + } + public void addItem(String name) { + choice.addItem(name); + } + public boolean handleEvent(Event event) { + if(event.id == Event.ACTION_EVENT) { + if(event.target instanceof Choice) { + mvp.showView(choice.getSelectedItem()); + } + } + return super.handleEvent(event); + } +} diff --git a/java/gjt/ColumnLayout.java b/java/gjt/ColumnLayout.java new file mode 100644 index 00000000000..bc51b44e456 --- /dev/null +++ b/java/gjt/ColumnLayout.java @@ -0,0 +1,154 @@ +package gjt; + +import java.awt.*; + +/** + * ColumnLayout lays out components in a column. At + * construction time, both horizontal orientation and vertical + * orientation may be specified, along with the gap to use + * between components.<p> + * + * Horizontal orientation must be one of the following: + * <dl> + * <dd> LEFT + * <dd> CENTER + * <dd> RIGHT + * </dl> + * + * Vertical orientation must be one of the following: + * <dl> + * <dd> TOP + * <dd> CENTER + * <dd> BOTTOM + * </dl> + * + * @version 1.0, Apr 1 1996 + * @author David Geary + * @see Orientation + * @see RowLayout + */ +public class ColumnLayout implements LayoutManager { + static private int _defaultGap = 5; + + private int gap; + private Orientation horizontalOrientation; + private Orientation verticalOrientation; + + public ColumnLayout() { + this(Orientation.CENTER, + Orientation.CENTER, _defaultGap); + } + public ColumnLayout(int gap) { + this(Orientation.CENTER, Orientation.CENTER, gap); + } + public ColumnLayout(Orientation horizontalOrient, + Orientation verticalOrient) { + this(horizontalOrient, verticalOrient, _defaultGap); + } + public ColumnLayout(Orientation horizontalOrient, + Orientation verticalOrient, int gap) { + Assert.notFalse(gap >= 0); + Assert.notFalse( + horizontalOrient == Orientation.LEFT || + horizontalOrient == Orientation.CENTER || + horizontalOrient == Orientation.RIGHT); + Assert.notFalse( + verticalOrient == Orientation.TOP || + verticalOrient == Orientation.CENTER || + verticalOrient == Orientation.BOTTOM); + + this.gap = gap; + this.verticalOrientation = verticalOrient; + this.horizontalOrientation = horizontalOrient; + } + + public void addLayoutComponent(String name, + Component comp) { + } + public void removeLayoutComponent(Component comp) { + } + + public Dimension preferredLayoutSize(Container target) { + Insets insets = target.insets(); + Dimension dim = new Dimension(0,0); + int ncomponents = target.countComponents(); + Component comp; + Dimension d; + + for (int i = 0 ; i < ncomponents ; i++) { + comp = target.getComponent(i); + + if(comp.isVisible()) { + d = comp.preferredSize(); + if(i > 0) + dim.height += gap; + + dim.height += d.height; + dim.width = Math.max(d.width, dim.width); + } + } + dim.width += insets.left + insets.right; + dim.height += insets.top + insets.bottom; + return dim; + } + public Dimension minimumLayoutSize(Container target) { + Insets insets = target.insets(); + Dimension dim = new Dimension(0,0); + int ncomponents = target.countComponents(); + Component comp; + Dimension d; + + for (int i = 0 ; i < ncomponents ; i++) { + comp = target.getComponent(i); + + if(comp.isVisible()) { + d = comp.minimumSize(); + + dim.width = Math.max(d.width, dim.width); + dim.height += d.height; + + if(i > 0) dim.height += gap; + } + } + dim.width += insets.left + insets.right; + dim.height += insets.top + insets.bottom; + + return dim; + } + public void layoutContainer(Container target) { + Insets insets = target.insets(); + int top = insets.top; + int left = 0; + int ncomponents = target.countComponents(); + Dimension preferredSize = target.preferredSize(); + Dimension targetSize = target.size(); + Component comp; + Dimension ps; + + if(verticalOrientation == Orientation.CENTER) + top += (targetSize.height/2) - + (preferredSize.height/2); + else if(verticalOrientation == Orientation.BOTTOM) + top = targetSize.height - preferredSize.height + + insets.top; + + for (int i = 0 ; i < ncomponents ; i++) { + comp = target.getComponent(i); + left = insets.left; + + if(comp.isVisible()) { + ps = comp.preferredSize(); + + if(horizontalOrientation == Orientation.CENTER) + left = (targetSize.width/2) - (ps.width/2); + else if( + horizontalOrientation == Orientation.RIGHT) { + left = targetSize.width - ps.width - + insets.right; + } + comp.reshape(left,top,ps.width,ps.height); + top += ps.height + gap; + } + } + } +} diff --git a/java/gjt/ComponentScroller.java b/java/gjt/ComponentScroller.java new file mode 100644 index 00000000000..3aef71c4ea2 --- /dev/null +++ b/java/gjt/ComponentScroller.java @@ -0,0 +1,42 @@ +package gjt; + +import java.awt.*; + +/** + * Scrolls any component. Component to be scrolled may be a + * container, so ultimately many components may be scrolled + * at once.<p> + * + * Component to be scrolled may be specified at construction + * time, or may be set after construction via + * void setComponent(Component).<p> + * + * @version 1.0, Apr 1 1996 + * @author David Geary + * @see BulletinLayout + * @see Scroller + * @see ScrollerLayout + * @see ImageScroller + * @see gjt.test.ComponentScrollerTest + */ +public class ComponentScroller extends Scroller { + private Component scrollMe; + + public ComponentScroller() { + } + public ComponentScroller(Component component) { + setComponent(component); + } + public void setComponent(Component component) { + scrollMe = component; + viewport.setLayout(new BulletinLayout()); + viewport.add (scrollMe); + viewport.move (0,0); + } + public void scrollTo(int x, int y) { + scrollMe.move(-x,-y); + } + public Dimension getScrollAreaSize() { + return scrollMe.preferredSize(); + } +} diff --git a/java/gjt/DialogClient.java b/java/gjt/DialogClient.java new file mode 100644 index 00000000000..7e67cea758e --- /dev/null +++ b/java/gjt/DialogClient.java @@ -0,0 +1,20 @@ +package gjt; + +import java.awt.Dialog; + +/** + * DialogClients are notified when the Dialog with which they + * are associated is dismissed. A reference to the dismissed + * Dialog is passed as a parameter of dialogDismissed() in case + * a DialogClient is a client of more than one Dialog.<p> + * + * @version 1.0, Apr 1 1996 + * @author David Geary + * @see MessageDialog + * @see QuestionDialog + * @see YesNoDialog + * @see gjt.test.DialogTest + */ +public interface DialogClient { + abstract public void dialogDismissed(Dialog d); +} diff --git a/java/gjt/DrawingPanel.java b/java/gjt/DrawingPanel.java new file mode 100644 index 00000000000..cda3fd69431 --- /dev/null +++ b/java/gjt/DrawingPanel.java @@ -0,0 +1,72 @@ +package gjt; + +import java.awt.*; +import gjt.rubberband.*; + +/** + * An extension of gjt.rubberband.RubberbandPanel which serves + * as a panel used for drawing simple shapes (lines, rectangles, + * and ellipses). The shapes may be filled (except for lines, + * of course), and the color of the shapes may be specified.<p> + * + * @version 1.0, Apr 1 1996 + * @author David Geary + * @see gjt.rubberband.RubberbandPanel + * @see gjt.rubberband.RubberbandEllipse + * @see gjt.rubberband.RubberbandLine + * @see gjt.rubberband.RubberbandRectangle + * @see gjt.test.RubberbandTest + * @see gjt.test.ToolbarTest + */ +public class DrawingPanel extends RubberbandPanel { + private Rubberband rbLine, rbRect, rbEllipse; + private Color color; + private boolean fill; + + public DrawingPanel() { + rbLine = new RubberbandLine (this); + rbRect = new RubberbandRectangle(this); + rbEllipse = new RubberbandEllipse (this); + + setRubberband(rbLine); + } + public void drawLines () { setRubberband(rbLine); } + public void drawRectangles() { setRubberband(rbRect); } + public void drawEllipses () { setRubberband(rbEllipse); } + + public void setColor(Color color) { this.color = color; } + public Color getColor() { return color; } + + public void setFill(boolean b) { fill = b; } + public boolean getFill() { return fill; } + + public boolean mouseUp(Event event, int x, int y) { + Rubberband rb = getRubberband(); + Graphics g = getGraphics(); + + super.mouseUp(event, x, y); + g.setColor(color); + + if(rb == rbLine) drawLine (rb, g); + else if(rb == rbRect) drawRectangle(rb, g); + else if(rb == rbEllipse) drawEllipse (rb, g); + + return true; + } + protected void drawLine(Rubberband rb, Graphics g) { + Point anchor = rb.getAnchor(), end = rb.getEnd(); + g.drawLine(anchor.x, anchor.y, end.x, end.y); + } + protected void drawRectangle(Rubberband rb, Graphics g) { + Rectangle r = rb.bounds(); + + if(fill) g.fillRect(r.x, r.y, r.width, r.height); + else g.drawRect(r.x, r.y, r.width, r.height); + } + protected void drawEllipse(Rubberband rb, Graphics g) { + Rectangle r = rb.bounds(); + + if(fill) g.fillArc(r.x, r.y, r.width, r.height, 0, 360); + else g.drawArc(r.x, r.y, r.width, r.height, 0, 360); + } +} diff --git a/java/gjt/DrawnRectangle.java b/java/gjt/DrawnRectangle.java new file mode 100644 index 00000000000..e96fd8d3673 --- /dev/null +++ b/java/gjt/DrawnRectangle.java @@ -0,0 +1,136 @@ +package gjt; + +import java.awt.*; + +/** + * A Rectangle which draws itself inside of a Component.<p> + * + * DrawnRectangles may have their thickness and line color set, + * and are capable of reporting their inner bounds (the area + * inside the lines).<p> + * + * Default thickness is 2.<p> + * + * If not set explicitly, the line color used is three shades + * darker than the background color of the Component being + * drawn into.<p> + * + * DrawnRectangles may be clear()ed, which clears both the + * exterior (the lines) and the interior (the area inside of + * the lines) of the DrawnRectangle.<p> + * + * DrawnRectangles may also be fill()ed with a specified color + * by calling fill(Color), or by calling setFillColor(Color) + * followed by fill().<p> + * + * By default, the fill Color is the background color of the + * Component drawn into.<p> + * + * @version 1.0, Apr 1 1996 + * @author David Geary + * @see ThreeDRectangle + * @see EtchedRectangle + * @see Border + * @see EtchedBorder + * @see ThreeDBorder + * @see gjt.test.DrawnRectangleTest + */ +public class DrawnRectangle extends Rectangle { + protected static int _defaultThickness = 2; + + protected Component drawInto; + private int thick; + private Color lineColor, fillColor; + + public DrawnRectangle(Component drawInto) { + this(drawInto, _defaultThickness, 0, 0, 0, 0); + } + public DrawnRectangle(Component drawInto, int thick) { + this(drawInto, thick, 0, 0, 0, 0); + } + public DrawnRectangle(Component drawInto, int x, int y, + int w, int h) { + this(drawInto, _defaultThickness, x, y, w, h); + } + public DrawnRectangle(Component drawInto, int thick, + int x, int y, int w, int h) { + Assert.notNull(drawInto); + Assert.notFalse(thick > 0); + + this.drawInto = drawInto; + this.thick = thick; + reshape(x,y,w,h); + } + public Component component() {return drawInto; } + public int getThickness () {return thick; } + public void setThickness (int thick) {this.thick = thick; } + + public void setLineColor(Color lineColor) { + this.lineColor = lineColor; + } + public void setFillColor(Color fillColor) { + this.fillColor = fillColor; + } + public void fill() { + fill(getFillColor()); + } + public Color getLineColor() { + if(lineColor == null) + lineColor = + drawInto.getBackground().darker().darker().darker(); + return lineColor; + } + public Color getFillColor() { + if(fillColor == null) + fillColor = drawInto.getBackground(); + return fillColor; + } + public Rectangle getInnerBounds() { + return new Rectangle(x+thick, y+thick, + width-(thick*2), height-(thick*2)); + } + public void paint() { + Graphics g = drawInto.getGraphics(); + paintFlat(g, getLineColor()); + } + private void paintFlat(Graphics g, Color color) { + if(g != null) { + g.setColor(color); + for(int i=0; i < thick; ++i) + g.drawRect(x+i, y+i, + width-(i*2)-1, height-(i*2)-1); + } + } + public void clearInterior() { + fill(drawInto.getBackground()); + } + public void clearExterior() { + paintFlat(drawInto.getGraphics(), + drawInto.getBackground()); + } + public void clear() { + clearExterior(); + clearInterior(); + } + public void fill(Color color) { + Graphics g = drawInto.getGraphics(); + + if(g != null) { + Rectangle r = getInnerBounds(); + g.setColor(color); + g.fillRect(r.x, r.y, r.width, r.height); + setFillColor(color); + } + } + public String toString() { + return super.toString() + "[" + paramString() + "]"; + } + public String paramString() { + return "color=" + getLineColor() + ",thickness=" + + thick + ",fillColor=" + getFillColor(); + } + protected Color brighter() { + return + getLineColor().brighter().brighter().brighter().brighter(); + } +} diff --git a/java/gjt/EtchedBorder.java b/java/gjt/EtchedBorder.java new file mode 100644 index 00000000000..09ff845014b --- /dev/null +++ b/java/gjt/EtchedBorder.java @@ -0,0 +1,59 @@ +package gjt; + +import java.awt.*; + +/** + * An extension of Border that draws an etched border. + * + * Drawn etchedIn by default, drawing style used by paint() is + * controlled by etchedIn() and etchedOut(). Note that + * etchedIn() and etchedOut() do not result in anything being + * painted, but only set the state for the next call to paint(). + * To set the state and paint in one operation, use + * paintEtchedIn() and paintEtchedOut().<p> + * + * The current state of the border may be obtained by calling + * isEtchedIn().<p> + * + * @version 1.0, Apr 1 1996 + * @author David Geary + * @see Border + * @see ThreeDRectangle + * @see gjt.test.BorderTest + */ +public class EtchedBorder extends Border { + public EtchedBorder(Component borderMe) { + this(borderMe, _defaultThickness, _defaultGap); + } + public EtchedBorder(Component borderMe, + int borderThickness) { + this(borderMe, borderThickness, _defaultGap); + } + public EtchedBorder(Component borderMe, + int borderThickness, int gap) { + super(borderMe, borderThickness, gap); + } + public void etchedIn() { + ((EtchedRectangle)border()).etchedIn(); + } + public void etchedOut() { + ((EtchedRectangle)border()).etchedOut(); + } + public void paintEtchedIn() { + ((EtchedRectangle)border()).paintEtchedIn (); + } + public void paintEtchedOut() { + ((EtchedRectangle)border()).paintEtchedOut(); + } + public boolean isEtchedIn() { + return ((EtchedRectangle)border()).isEtchedIn(); + } + protected String paramString() { + return super.paramString() + (EtchedRectangle)border(); + } + protected DrawnRectangle border() { + if(border == null) + border = new EtchedRectangle(this, thickness); + return border; + } +} diff --git a/java/gjt/EtchedRectangle.java b/java/gjt/EtchedRectangle.java new file mode 100644 index 00000000000..b8026d42f8d --- /dev/null +++ b/java/gjt/EtchedRectangle.java @@ -0,0 +1,97 @@ +package gjt; + +import java.awt.*; + +/** + * A DrawnRectangle that draws an etched border.<p> + * + * Drawn etched in by default, drawing style used by paint() is + * controlled by etchedIn() and etchedOut(). Note that + * etchedIn() and etchedOut() do not result in anything being + * painted, but only set the state for the next call to paint(). + * To set the state and paint in one operation, use + * paintEtchedIn() and paintEtchedOut().<p> + * + * Although it is permissible to set the thickness of + * EtchedRectangles, they tend to loose the etching effect + * if thickness is greater than 4.<p> + * + * The current state of the rectangle may be obtained by + * calling isEtchedIn(). + * + * @version 1.0, Apr 1 1996 + * @author David Geary + * @see DrawnRectangle + * @see ThreeDRectangle + * @see gjt.test.DrawnRectangleTest + */ +public class EtchedRectangle extends DrawnRectangle { + protected static Etching _defaultEtching = Etching.IN; + private Etching etching; + + public EtchedRectangle(Component drawInto) { + this(drawInto, _defaultEtching, + _defaultThickness, 0, 0, 0, 0); + } + public EtchedRectangle(Component drawInto, int thickness) { + this(drawInto, _defaultEtching, thickness, 0, 0, 0, 0); + } + public EtchedRectangle(Component drawInto, int x, int y, + int w, int h) { + this(drawInto, _defaultEtching, + _defaultThickness, x, y, w, h); + } + public EtchedRectangle(Component drawInto, int thickness, + int x, int y, + int w, int h) { + this(drawInto, _defaultEtching, thickness, x, y, w, h); + } + public EtchedRectangle(Component drawInto, Etching etching, + int thickness, int x, int y, + int w, int h) { + super(drawInto, thickness, x, y, w, h); + this.etching = etching; + } + public void etchedIn () { etching = Etching.IN; } + public void etchedOut () { etching = Etching.OUT; } + public boolean isEtchedIn() { return etching == Etching.IN;} + + public void paint() { + if(etching == Etching.IN) paintEtchedIn(); + else paintEtchedOut(); + } + public void paintEtchedIn() { + Graphics g = drawInto.getGraphics(); + if(g != null) + paintEtched(g, getLineColor(), brighter()); + + etchedIn(); + } + public void paintEtchedOut() { + Graphics g = drawInto.getGraphics(); + if(g != null) + paintEtched(g, brighter(), getLineColor()); + + etchedOut(); + } + public String paramString() { + return super.paramString() + "," + etching; + } + private void paintEtched(Graphics g, + Color topLeft, + Color bottomRight) { + int thickness = getThickness(); + int w = width - thickness; + int h = height - thickness; + + g.setColor(topLeft); + for(int i=0; i < thickness/2; ++i) + g.drawRect(x+i, y+i, w, h); + + g.setColor(bottomRight); + + for(int i=0; i < thickness/2; ++i) + g.drawRect(x+(thickness/2)+i, + y+(thickness/2)+i, w, h); + } +} diff --git a/java/gjt/Etching.java b/java/gjt/Etching.java new file mode 100644 index 00000000000..ad40d9caaea --- /dev/null +++ b/java/gjt/Etching.java @@ -0,0 +1,22 @@ +package gjt; + +/** + * Constants for Etching. + * + * This class may not be instantiated. + * + * @version 1.0, Apr 11 1996 + * @author David Geary + */ +public class Etching { + public static final Etching OUT = new Etching(); + public static final Etching IN = new Etching(); + + public String toString() { + if(this == Etching.OUT) + return getClass().getName() + "=OUT"; + else + return getClass().getName() + "=IN"; + } + private Etching() { } +} diff --git a/java/gjt/ExclusiveImageButtonPanel.java b/java/gjt/ExclusiveImageButtonPanel.java new file mode 100644 index 00000000000..f1d0878a499 --- /dev/null +++ b/java/gjt/ExclusiveImageButtonPanel.java @@ -0,0 +1,47 @@ +package gjt; + +import java.awt.Image; + +/** + * An ImageButtonPanel which fits all of its ImageButtons with + * a StickyImageButtonController. ExclusiveImageButtonPanel + * relies upon its superclass' controller: a + * RadioImageButtonPanelController, which ensures that only one + * of the ImageButtons is selected at a time.<p> + * + * @version 1.0, Apr 1 1996 + * @author David Geary + * @see ImageButton + * @see ImageButtonPanel + * @see gjt.test.ToolbarTest + */ +public class ExclusiveImageButtonPanel extends + ImageButtonPanel { + public ExclusiveImageButtonPanel(Orientation orient) { + this(orient, 5); + } + public ExclusiveImageButtonPanel(Orientation orient, + int gap) { + super(orient, gap); + } + public ExclusiveImageButtonPanel(Orientation orient, + Orientation horient, + Orientation vorient, + int gap) { + super(orient, horient, vorient, gap); + } + public void add(ImageButton button) { + super.add(button); + new StickyImageButtonController(button); + } + public ImageButton add(Image image) { + ImageButton button = super.add(image); + new StickyImageButtonController(button); + return button; + } + public ImageButton add(Image image, String name) { + ImageButton button = super.add(image, name); + new StickyImageButtonController(button); + return button; + } +} diff --git a/java/gjt/FontDialog.java b/java/gjt/FontDialog.java new file mode 100644 index 00000000000..182ca582884 --- /dev/null +++ b/java/gjt/FontDialog.java @@ -0,0 +1,362 @@ +package gjt; + +import java.awt.*; + +/** + * A dialog used for selecting a font. FontDialog is + * constructed with a Frame, DialogClient, initial font to + * display, and boolean that indicates modality.<p> + * + * FontDialog contains a preview panel which previews the + * currently selected font. Updating of the preview panel is + * triggered by a preview button at the bottom of the dialog.<p> + * + * FontDialog contains 3 methods which define the labels for + * the buttons it contains: + * <dl> + * <dd> String getPreviewButtonLabel() + * <dd> String getOkButtonLabel() + * <dd> String getCancelButtonLabel() + * </dl><p> + * + * By default the 3 methods return "Preview", "Ok" and "Cancel" + * respectively. FontDialog may be extended and the 3 methods + * overridden to customize the labels displayed in the + * buttons.<p> + * + * FontDialog uses Toolkit to get a list of fonts by invoking + * Toolkit.getFontList(). This is done in the getFontNames() + * method, which may be overridden by extensions of FontDialog + * in case the standard set of font names are inadequate.<p> + * + * Finally, font sizes are obtained by the getFontSizes() + * method. FontDialog defines 8 sizes by default: 8, 12, 14, + * 16, 18, 24, 48 and 64. Extensions of FontDialog may override + * getFontSizes() to provide a different list of sizes.<p> + * + * See gjt.test.FontDialogTest for an example of an extension + * of FontDialog which overrides the methods discussed above.<p> + * + * @version 1.0, Apr 1 1996 + * @author David Geary + * @see java.awt.Dialog + * @see java.awt.Toolkit + * @see DialogClient + * @see gjt.test.FontDialogTest + */ +public class FontDialog extends Dialog { + private static String _defaultSizes[] = + { "8", "12", "14", "16", "18", "24", "48", "64" }; + + private FontPanel fontPanel; + private Font fontSelected; + private DialogClient client; + + public FontDialog(Frame frame, + DialogClient client, + Font font, // initial font + boolean modal) { + super(frame, "Select A Font", modal); + this.client = client; + + setLayout(new BorderLayout()); + add("Center", fontPanel = new FontPanel(this, font)); + } + public boolean handleEvent(Event event) { + if(event.id == Event.WINDOW_DESTROY) + done(null); + + return super.handleEvent(event); + } + public String[] getFontNames() { + return getToolkit().getFontList(); + } + public String[] getFontSizes() { + return _defaultSizes; + } + + public String getPreviewButtonLabel() { return "Preview"; } + public String getOkButtonLabel () { return "Ok"; } + public String getCancelButtonLabel () { return "Cancel"; } + + public void show() { + Point frameLoc = getParent().location(); + reshape(frameLoc.x + 50, frameLoc.x + 50, 550, 450); + super.show(); + } + public void done(Font font) { + fontSelected = font; + client.dialogDismissed(this); + hide (); + dispose(); + } + public Font getFontSelected() { + return fontSelected; + } + public void listSelectedInPicker() { + fontPanel.getPreviewButton().requestFocus(); + } +} + +class FontPanel extends Panel { + private static Font defaultFont = + new Font("TimesRoman", Font.PLAIN, 12); + + private FontPreviewPanel preview; + private FontSelectionPanel fsp; + + public FontPanel(FontDialog dialog, Font f) { + Font font = f == null ? defaultFont : f; + + setLayout(new BorderLayout()); + add("North", preview = new FontPreviewPanel ()); + add("Center", fsp = + new FontSelectionPanel(dialog, preview, font)); + } + public Button getPreviewButton() { + return fsp.getPreviewButton(); + } +} + +class FontPreviewPanel extends Panel { + TextField textField = new TextField(); + Box box = new Box(textField, "Preview"); + + public FontPreviewPanel() { + textField.setEditable(false); + + setLayout(new BorderLayout()); + add("Center", box); + } + public void setPreviewFont(Font font) { + String name = font.getName(); + String size = String.valueOf(font.getSize()); + String style = new String(); + + if(font.isPlain () == true) style = "Plain"; + else { + if(font.isBold () == true) style += "Bold"; + if(font.isItalic() == true) style += "Italic"; + } + textField.setFont(font); + textField.setText(name + " " + style + " " + size); + retrofitPreviewPanel(); + } + private void retrofitPreviewPanel() { + Dimension tfps, tfs; + FontPanel fontPanel = (FontPanel)getParent(); + + tfps = textField.preferredSize(); + tfs = textField.size(); + + if(tfps.width != tfs.width || + tfps.height != tfs.height) { + fontPanel.invalidate(); + fontPanel.getParent().validate(); + box.repaint(); // Only necessary on Win95 + } + } +} + +class FontSelectionPanel extends Panel { + private FontPickerPanel picker; + private FontButtonsPanel buttons; + private FontPreviewPanel preview; + private Font initialFont; + + public FontSelectionPanel(FontDialog dialog, + FontPreviewPanel preview, + Font initialFont) { + this.preview = preview; + this.initialFont = initialFont; + + picker = new FontPickerPanel (dialog, initialFont); + buttons = new FontButtonsPanel(dialog, picker, preview); + + setLayout(new BorderLayout()); + add("Center", picker); + add("South", buttons); + } + public void addNotify() { + super.addNotify(); + preview.setPreviewFont(initialFont); + } + public Button getPreviewButton() { + return buttons.getPreviewButton(); + } +} + +class FontPickerPanel extends Panel { + private FontDialog dialog; + private Button previewButton; + private List fonts = new List(); + private List styles = new List(); + private List sizes = new List(); + private Font initialFont; + + public FontPickerPanel(FontDialog dialog, + Font initialFont) { + GridBagLayout gbl = new GridBagLayout(); + GridBagConstraints gbc = new GridBagConstraints(); + Label family = new Label("Family"); + Label style = new Label("Style"); + Label size = new Label("Size"); + + this.initialFont = initialFont; + this.dialog = dialog; + + populateFonts (); + populateStyles(); + populateSizes (); + + setLayout(gbl); + + gbc.anchor = GridBagConstraints.NORTH; + gbc.gridwidth = 1; + gbl.setConstraints(family, gbc); add(family); + gbl.setConstraints(style, gbc); add(style); + gbc.gridwidth = GridBagConstraints.REMAINDER; + gbl.setConstraints(size, gbc); add(size); + + gbc.gridwidth = 1; + gbc.weighty = 1.0; + gbc.weightx = 1.0; + gbc.fill = GridBagConstraints.BOTH; + gbl.setConstraints(fonts, gbc); add(fonts); + gbl.setConstraints(styles, gbc); add(styles); + gbl.setConstraints(sizes, gbc); add(sizes); + } + public boolean handleEvent(Event event) { + if(event.id == Event.LIST_SELECT) { + dialog.listSelectedInPicker(); + return true; + } + return false; + } + public void addNotify() { + super.addNotify(); + String initialFamily = initialFont.getName(); + int initialSize = initialFont.getSize(); + int initialStyle = initialFont.getStyle(); + + styles.select(initialStyle); + + for(int i=0; i < fonts.countItems(); ++i) { + String nextFamily = fonts.getItem(i); + if(nextFamily.equals(initialFamily)) + fonts.select(i); + } + for(int i=0; i < sizes.countItems(); ++i) { + String nextSize = sizes.getItem(i); + if(nextSize.equals(String.valueOf(initialSize))) + sizes.select(i); + } + } + public String fontSelected() { + return fonts.getSelectedItem (); + } + public String styleSelected() { + return styles.getSelectedItem(); + } + public int sizeSelected() { + String szstring = sizes.getSelectedItem(); + + if(szstring != null) { + Integer integer = new Integer(szstring); + return integer.intValue(); + } + else + return 0; + } + private void populateFonts() { + String names[] = dialog.getFontNames(); + + for(int i=0; i < names.length; ++i) { + fonts.addItem(names[i]); + } + } + private void populateSizes() { + String sizeArray[] = dialog.getFontSizes(); + + for(int i=0; i < sizeArray.length; ++i) { + sizes.addItem(sizeArray[i]); + } + } + private void populateStyles() { + styles.addItem("Plain"); + styles.addItem("Bold"); + styles.addItem("Italic"); + styles.addItem("BoldItalic"); + } +} + +class FontButtonsPanel extends Panel { + private FontDialog dialog; + private FontPickerPanel picker; + private FontPreviewPanel preview; + private Button previewButton, + okButton, + cancelButton; + + public FontButtonsPanel(FontDialog dialog, + FontPickerPanel picker, + FontPreviewPanel preview) { + this.picker = picker; + this.preview = preview; + this.dialog = dialog; + + add(previewButton = + new Button(dialog.getPreviewButtonLabel())); + add(cancelButton = + new Button(dialog.getCancelButtonLabel())); + add(okButton = + new Button(dialog.getOkButtonLabel())); + } + public void addNotify() { + super.addNotify(); + cancelButton.requestFocus(); + } + public boolean action(Event event, Object object) { + Button button = (Button)event.target; + boolean handledEvent = true; + + if(event.target == previewButton) { + Font selectedFont = fontSelected(); + + if(selectedFont != null) { + preview.setPreviewFont(selectedFont); + okButton.requestFocus(); + } + } + else if(event.target == okButton) + dialog.done(fontSelected()); + else if(event.target == cancelButton) + dialog.done(null); + else + handledEvent = false; + + return handledEvent; + } + public Button getPreviewButton() { + return previewButton; + } + private Font fontSelected() { + String font = picker.fontSelected (); + String style = picker.styleSelected(); + int size = picker.sizeSelected (); + int istyle = Font.PLAIN; + + if(font != null && style != null && size > 0) { + if(style.equals("Bold")) istyle = Font.BOLD; + if(style.equals("Plain")) istyle = Font.PLAIN; + if(style.equals("Italic")) istyle = Font.ITALIC; + + if(style.equals("BoldItalic")) + istyle = Font.BOLD + Font.ITALIC; + + return new Font(font, istyle, size); + } + else + return null; + } +} diff --git a/java/gjt/GJTDialog.java b/java/gjt/GJTDialog.java new file mode 100644 index 00000000000..7fc0bd39f40 --- /dev/null +++ b/java/gjt/GJTDialog.java @@ -0,0 +1,51 @@ +package gjt; + +import java.awt.*; + +/** + * A base class for gjt dialog classes, this concrete class + * establishes the relationship between a dialog and its + * client (DialogClient).<p> + * + * Note that show() is overridden to ensure that the dialog is + * centered in the frame which is specified as its parent. This + * is necessary due to a bug in the Win95 implementation of the + * AWT (version 1.0.2) that causes dialogs to be displayed at + * a screen coordinate of 0,0. While the overridden show() is + * not necessary under non-Win95 Java implementations, it + * alleviates the Win95 bug and results in no dire consequences + * on other platforms.<p> + * + * @version 1.0, Apr 1 1996 + * @author David Geary + * @see MessageDialog + * @see QuestionDialog + * @see YesNoDialog + * @see ProgressDialog + * @see gjt.test.DialogTest + */ +public class GJTDialog extends Dialog { + protected DialogClient client; + + public GJTDialog(Frame frame, + String title, + DialogClient client, + boolean modal) { + super(frame, title, modal); + setClient(client); + } + public void setClient(DialogClient client) { + this.client = client; + } + public void show() { // Fixes bug under Win95 + Dimension frameSize = getParent().size(); + Point frameLoc = getParent().location(); + Dimension mySize = size(); + int x,y; + + x = frameLoc.x + (frameSize.width/2) -(mySize.width/2); + y = frameLoc.y + (frameSize.height/2)-(mySize.height/2); + reshape(x,y,size().width,size().height); + super.show(); + } +} diff --git a/java/gjt/IconCardPanel.java b/java/gjt/IconCardPanel.java new file mode 100644 index 00000000000..78940bf8f4f --- /dev/null +++ b/java/gjt/IconCardPanel.java @@ -0,0 +1,55 @@ +package gjt; + +import java.awt.*; + +/** + * A CardPanel whose Component viewSelector() returns + * a panel with image buttons to control the selection of the + * panel to be displayed beneath the view selector panel.<p> + * + * @version 1.0, Apr 1 1996 + * @author David Geary + * @see CardPanel + * @see ChoiceCardpanel + * @see gjt.test.IconCardPanelTest + */ +public class IconCardPanel extends CardPanel { + private ImageButtonPanel viewSelector; + + public IconCardPanel() { + viewSelector = new IconViewSelector(this); + } + public Component viewSelector() { + return viewSelector; + } + public void addImageButton(Image image, + String name, + Component component) { + ImageButton newButton; + + viewSelector.add( + newButton = new ImageButton(image), name); + newButton.setController( + new StickyImageButtonController(newButton)); + super.addView(name, component); + } +} + +class IconViewSelector extends ImageButtonPanel { + private IconCardPanel mvp; + + public IconViewSelector(IconCardPanel panel) { + super(Orientation.HORIZONTAL); + setLayout(new FlowLayout()); + mvp = panel; + } + public boolean handleEvent(Event event) { + if(event.id == Event.MOUSE_DOWN) { + if(event.target instanceof ImageButton) { + ImageButton ib = (ImageButton)event.target; + mvp.showView(getButtonName(ib)); + } + } + return super.handleEvent(event); + } +} diff --git a/java/gjt/ImageButton.java b/java/gjt/ImageButton.java new file mode 100644 index 00000000000..07bdeff0ef8 --- /dev/null +++ b/java/gjt/ImageButton.java @@ -0,0 +1,209 @@ +package gjt; + +import java.awt.*; +import java.awt.image.FilteredImageSource; + +import gjt.image.BleachImageFilter; + +/** + * An Image painted in a Canvas, bordered by a ThreeDRectangle. + * <p> + * + * ImageButtons have two constructors, both of which take an + * Image. The Image passed to the constructor must not be null; + * this is enforced by an assertion.<p> + * + * Default border thickness is 2 pixels - thickness may be set + * at construction time only.<p> + * + * Event handling is delegated to an ImageButtonController. By + * default, all ImageButtons are fitted with an instance of + * SpringyImageButtonController, however, + * setController(ImageButtonController) may be used to fit an + * ImageButton with a different derivation of + * ImageButtonController after construction.<p> + * + * ImageButtons ensure that their Images are completely loaded + * before they are displayed.<p> + * + * Drawn either raised or inset, current state may be queried + * via the isRaised() method.<p> + * + * disable() disables response to input and repaints the image + * with a bleached version. enable() restores the original + * image and enables response to input. The intensity of the + * bleaching effect may be controlled (for all ImageButtons) + * via the static setBleachPercent(int) method.<p> + * + * @version 1.0, Apr 1 1996 + * @author David Geary + * @see ThreeDRectangle + * @see ImageButtonController + * @see ImageButtonEvent + * @see SpringyImageButtonController + * @see StickyImageButtonController + * @see BleachImageFilter + * @see gjt.test.ImageButtonTest + */ +public class ImageButton extends Canvas { + private static BleachImageFilter _bleachFilter; + private static int _bleachPercent = 50; + private static int _offset = 1; + private static int _defaultThickness = 2; + + private ThreeDRectangle border = new ThreeDRectangle(this); + private boolean isDisabled = false; + private Dimension preferredSize = new Dimension(0,0); + private int thickness; + private Image image, disabledImage; + private ImageButtonController controller; + + public static int setBleachPercent() { + return _bleachPercent; + } + public static void getBleachPercent(int p) { + _bleachPercent = p; + } + public ImageButton(Image image) { + this(image, _defaultThickness, null); + } + public ImageButton(Image image, + ImageButtonController controller) { + this(image, _defaultThickness, controller); + } + public ImageButton(Image image, int thickness, + ImageButtonController controller) { + Assert.notNull(image); + Assert.notFalse(thickness > 0); + + if(controller == null) + this.controller = + new SpringyImageButtonController(this); + else + this.controller = controller; + + border.setThickness(this.thickness = thickness); + setImage(image); + } + public void setImage(Image image) { + Util.waitForImage(this, this.image = image); + + preferredSize.width = image.getWidth (this) + + (2*thickness); + preferredSize.height = image.getHeight(this) + + (2*thickness); + } + public Dimension minimumSize() { + return preferredSize; + } + public Dimension preferredSize() { + return preferredSize; + } + public boolean isRaised () { return border.isRaised(); } + public boolean isDisabled() { return isDisabled; } + + public void enable() { + isDisabled = false; + repaint(); + } + public void disable() { + isDisabled = true; + + if(disabledImage == null) + createDisabledImage(); + + repaint(); + } + public void resize(int w, int h) { + reshape(location().x, location().y, w, h); + } + public void reshape(int x, int y, int w, int h) { + super.reshape(x,y,w,h); + border.resize(w,h); + } + public void paint(Graphics g) { + if(isRaised()) paintRaised(); + else paintInset (); + } + public void paintInset() { + Point upperLeft = findUpperLeft(); + Graphics g = getGraphics(); + Image image = isDisabled() ? + disabledImage : this.image; + Dimension size = size(); + + if(g != null) { + border.clearInterior(); + g.drawImage(image, + upperLeft.x + thickness + _offset, + upperLeft.y + thickness + _offset,this); + + g.setColor(getBackground().darker()); + for(int i=0; i < _offset; ++i) { + g.drawLine(thickness+i,thickness+i, + size.width-thickness-i,thickness+i); + g.drawLine(thickness+i,thickness+i, + thickness+i,size.height-thickness-i); + } + border.paintInset(); + } + } + public void paintRaised() { + Point upperLeft = findUpperLeft(); + Graphics g = getGraphics(); + Image image = isDisabled() ? + disabledImage : this.image; + + if(g != null) { + border.clearInterior(); + g.drawImage(image, upperLeft.x + thickness, + upperLeft.y + thickness, this); + border.paintRaised(); + } + } + public boolean isInside(int x, int y) { + Dimension size = size(); + return x >= 0 && x < size.width && y >= 0 && + y < size.height; + } + public void setController(ImageButtonController controller){ + this.controller = controller; + } + public ImageButtonController getController() { + return controller; + } + public boolean mouseDown(Event event, int x, int y) { + if(isDisabled()) return false; + else return controller.mouseDown(event,x,y); + } + public boolean mouseUp(Event event, int x, int y) { + if(isDisabled()) return false; + else return controller.mouseUp(event,x,y); + } + public boolean mouseDrag(Event event, int x, int y) { + if(isDisabled()) return false; + else return controller.mouseDrag(event,x,y); + } + + private void createDisabledImage() { + if(_bleachFilter == null) + _bleachFilter = + new BleachImageFilter(_bleachPercent); + + if(_bleachPercent != _bleachFilter.percent()) + _bleachFilter.percent(_bleachPercent); + + FilteredImageSource fis = + new FilteredImageSource(image.getSource(), + _bleachFilter); + + Util.waitForImage(this, disabledImage=createImage(fis)); + } + private Point findUpperLeft() { + Dimension size = size(); + return new Point((size.width/2) - + (preferredSize.width/2), + (size.height/2) - + (preferredSize.height/2)); + } +} diff --git a/java/gjt/ImageButtonController.java b/java/gjt/ImageButtonController.java new file mode 100644 index 00000000000..0f6aa6f4add --- /dev/null +++ b/java/gjt/ImageButtonController.java @@ -0,0 +1,79 @@ +package gjt; +import java.awt.Event; + +/** + * A controller for an ImageButton, this abstract class + * establishes the association between itself and an ImageButton + * and delivers events to its ImageButton.<p> + * + * ImageButtonControllers must be constructed with an + * ImageButton; the ImageButton's controller gets set by + * ImageButtonController's constructor.<p> + * + * The ImageButton passed into the constructor must not be null; + * this is enforced by an assertion.<p> + * + * Methods defined in the MouseController interface are left + * for subclasses to implement. ImageButtonController defines + * mouseMove(), mouseEnter() and mouseExit() as no-ops, so + * that extensions of ImageButtonController only have to + * implement mouseDown(), mouseUp() and mouseDrag(). Note + * that extensions are still free to override mouseMove(), + * mouseEnter() and mouseExit() if desired.<p> + * + * Subclasses should also call the protected XXXButton(Event) + * methods below, where XXX is either arm, disarm, activate, or + * deactivate as appropriate. SpringyImageButtonController is + * a good example of this (so is StickyImageButtonController, + * but it is more complicated than it's springy sibling).<p> + * + * @version 1.0, Apr 1 1996 + * @author David Geary + * @see MouseController + * @see ImageButton + * @see ImageButtonEvent + * @see SpringyImageButtonController + * @see StickyImageButtonController + * @see gjt.test.ImageButtonTest + */ +public abstract class ImageButtonController + implements MouseController { + private ImageButton button; + + ImageButtonController(ImageButton button) { + Assert.notNull(button); + this.button = button; + button.setController(this); + } + public ImageButton getButton() { + return button; + } + public boolean mouseEnter(Event event, int x, int y) { + return false; + } + public boolean mouseExit (Event event, int x, int y) { + return false; + } + public boolean mouseMove (Event event, int x, int y) { + return false; + } + + protected void armButton(Event event) { + button.deliverEvent( + new ImageButtonEvent(button, + event, + ImageButtonEvent.ARM)); + } + protected void disarmButton(Event event) { + button.deliverEvent( + new ImageButtonEvent(button, + event, + ImageButtonEvent.DISARM)); + } + protected void activateButton(Event event) { + button.deliverEvent( + new ImageButtonEvent(button, + event, + ImageButtonEvent.ACTIVATE)); + } +} diff --git a/java/gjt/ImageButtonEvent.java b/java/gjt/ImageButtonEvent.java new file mode 100644 index 00000000000..bb7f196698f --- /dev/null +++ b/java/gjt/ImageButtonEvent.java @@ -0,0 +1,103 @@ +package gjt; + +import java.awt.Event; + +/** + * An extension of java.awt.Event, specifically designed for + * ImageButton events.<p> + * + * ImageButtonEvents are constructed with 3 arguments: + * <dl> + * <dd> ImageButton in which the event occurred + * <dd> The AWT event that triggered the image button event + * <dd> The id of the event. + * </dl> + * + * An ImageButtonEvent's id (the constructor's 3rd argument), + * must be one of the following: + * + * <dl> + * <dd> ImageButtonEvent.ARM + * <dd> ImageButtonEvent.DISARM + * <dd> ImageButtonEvent.ACTIVATE + * </dl> + * + * ImageButtonEvent has only a constructor and a paramString() + * method. Containers that contain ImageButtons should check + * for ImageButtonEvents like so: <p> + * + * <pre> + * // handleEvent(Event) method of a container that + * // contains ImageButtons. + * + * public boolean handleEvent(Event event) { + * if(event instanceof ImageButtonEvent) { + * ImageButtonEvent ibevent = + * (ImageButtonEvent)event; + * + * if(ibevent.isArmed()) { + * // do something for arming + * } + * if(ibevent.isDisarmed()) { + * // do something for disarming + * } + * if(ibevent.isActivated()) { + * // do something for activation + * } + * } + * } + * </pre> + * + * ImageButtonController is the only GJT class that creates + * ImageButtonEvents. + * + * @version 1.0, Apr 1 1996 + * @author David Geary + * @see ImageButton + * @see ImageButtonController + * @see SpringyImageButtonController + * @see StickyImageButtonController + * @see gjt.test.ImageButtonTest + */ +public class ImageButtonEvent extends Event { + public static final int ARM = 1; + public static final int DISARM = 2; + public static final int ACTIVATE = 3; + + private int eventType; + + public ImageButtonEvent(ImageButton button, + Event event, + int type) { + super(button, event.when, event.id, event.x, event.y, + event.key, event.modifiers, event.arg); + + Assert.notFalse(type == ARM || + type == DISARM || + type == ACTIVATE); + + eventType = type; + id = -1; + } + public boolean isArmed() { + return eventType == ARM; + } + public boolean isDisarmed() { + return eventType == DISARM; + } + public boolean isActivated() { + return eventType == ACTIVATE; + } + protected String paramString() { + String str = new String(); + + if(eventType == ImageButtonEvent.ARM) + str = "ARM"; + else if(eventType == ImageButtonEvent.DISARM) + str = "DISARM"; + else if(eventType == ImageButtonEvent.ACTIVATE) + str = "ACTIVATE"; + + return super.paramString() + str; + } +} diff --git a/java/gjt/ImageButtonPanel.java b/java/gjt/ImageButtonPanel.java new file mode 100644 index 00000000000..0d033b7967b --- /dev/null +++ b/java/gjt/ImageButtonPanel.java @@ -0,0 +1,106 @@ +package gjt; + +import java.awt.*; +import java.util.Enumeration; +import java.util.Hashtable; + +/** + * A panel which contains a collection of ImageButtons, + * arranged either horizontally or vertically.<p> + * + * Handling of mouse events is delegated to an image button + * panel controller. By default, an image button panel is + * outfitted with an instance of RadioImageButtonPanelController + * which implements mutually exclusive selection behavior. + * + * @version 1.0, Apr 1 1996 + * @author David Geary + * @see ImageButton + * @see RadioImageButtonPanelController + * @see gjt.test.ToolbarTest + */ +public class ImageButtonPanel extends Panel { + static private int _defaultGap = 5; + + private Hashtable nameAndButtonPairs = new Hashtable(); + private ImageButtonPanelController controller; + + public ImageButtonPanel(Orientation orient) { + this(orient, Orientation.CENTER, + Orientation.CENTER, _defaultGap); + } + public ImageButtonPanel(Orientation orient, int gap) { + this(orient, Orientation.CENTER, + Orientation.CENTER, gap); + } + public ImageButtonPanel(Orientation orient, + Orientation horient, + Orientation vorient, int gap) { + Assert.notFalse(orient == Orientation.HORIZONTAL || + orient == Orientation.VERTICAL); + + if(orient == Orientation.VERTICAL) + setLayout(new ColumnLayout(horient, vorient, gap)); + else + setLayout(new RowLayout(horient, vorient, gap)); + + setController( + new RadioImageButtonPanelController(this)); + } + public void setController(ImageButtonPanelController c) { + this.controller = c; + } + public Insets insets() { return new Insets(10,10,10,10); } + + public ImageButton add(Image image, String name) { + ImageButton button = new ImageButton(image); + add(button); + nameAndButtonPairs.put(name, button); + return button; + } + public ImageButton add(Image image) { + return add(image, "noname"); + } + public void add(ImageButton button) { + add(button, "noname"); + } + public void add(ImageButton button, String name) { + nameAndButtonPairs.put(name, button); + super.add(button); + } + public ImageButton getButtonByName(String name) { + return (ImageButton)nameAndButtonPairs.get(name); + } + public String getButtonName(ImageButton button) { + Enumeration e = nameAndButtonPairs.keys(); + ImageButton nbutt; + String nstr; + + while(e.hasMoreElements()) { + nstr = (String)e.nextElement(); + nbutt = (ImageButton)nameAndButtonPairs.get(nstr); + + if(nbutt.equals(button)) + return nstr; + } + return null; + } + public void addSpacer(int sizeInPixels) { + Assert.notFalse(sizeInPixels > 0); + Canvas spacer = new Canvas(); + spacer.resize(sizeInPixels, sizeInPixels); + add(spacer); + } + public boolean mouseDown(Event event, int x, int y) { + return controller != null ? + controller.mouseDown(event,x,y) : false; + } + public boolean mouseDrag(Event event, int x, int y) { + return controller != null ? + controller.mouseDrag(event,x,y) : false; + } + public boolean mouseUp(Event event, int x, int y) { + return controller != null ? + controller.mouseUp(event,x,y) : false; + } +} diff --git a/java/gjt/ImageButtonPanelController.java b/java/gjt/ImageButtonPanelController.java new file mode 100644 index 00000000000..74f900001b6 --- /dev/null +++ b/java/gjt/ImageButtonPanelController.java @@ -0,0 +1,47 @@ +package gjt; + +import java.awt.Event; + +/** + * A controller for an ImageButtonPanel, this abstract class + * does nothing more than establish the association between an + * ImageButton and its controller.<p> + * + * ImageButtonControllers must be constructed with an + * ImageButtonPanel; the ImageButtonPanels' controller gets set + * by the constructor.<p> + * + * The ImageButton passed into the constructor must not be null; + * this is enforced by an assertion.<p> + * + * Methods defined in the MouseController interface are left + * for subclasses to implement.<p> + * + * @version 1.0, Apr 1 1996 + * @author David Geary + * @see MouseController + * @see ImageButtonPanel + * @see gjt.test.Toolbar + */ +abstract class ImageButtonPanelController implements + MouseController { + private ImageButtonPanel panel; + + ImageButtonPanelController(ImageButtonPanel panel) { + Assert.notNull(panel); + this.panel = panel; + panel.setController(this); + } + public ImageButtonPanel panel() { + return panel; + } + public boolean mouseEnter(Event event, int x, int y) { + return false; + } + public boolean mouseExit (Event event, int x, int y) { + return false; + } + public boolean mouseMove (Event event, int x, int y) { + return false; + } +} diff --git a/java/gjt/ImageCanvas.java b/java/gjt/ImageCanvas.java new file mode 100644 index 00000000000..49e3bc72f3f --- /dev/null +++ b/java/gjt/ImageCanvas.java @@ -0,0 +1,31 @@ +package gjt; + +import java.awt.*; + +/** + * A Canvas that displays an image.<p> + * + * update() is overridden to call paint() directly, thus + * bypassing the default implementation of update() which + * erases the background of the canvas before calling paint(). + * This eliminates nasty flashing.<p> + * + * @version 1.0, Apr 1 1996 + * @author David Geary + * @see Util + */ +class ImageCanvas extends Canvas { + private Image image; + + public ImageCanvas(Image image) { + this.image = image; + Util.waitForImage(this, image); + resize(image.getWidth(this), image.getHeight(this)); + } + public void paint(Graphics g) { + g.drawImage(image, 0, 0, this); + } + public void update(Graphics g) { + paint(g); + } +} diff --git a/java/gjt/ImageScroller.java b/java/gjt/ImageScroller.java new file mode 100644 index 00000000000..79fdc86ea3c --- /dev/null +++ b/java/gjt/ImageScroller.java @@ -0,0 +1,62 @@ +package gjt; + +import java.awt.*; + +/** + * An extension of Scroller that smoothly scrolls an Image.<p> + * + * An Image must be supplied at construction time. The image + * may be reset any time after construction.<p> + * + * @version 1.0, Apr 1 1996 + * @author David Geary + * @see Scroller + * @see ImageCanvas + * @see gjt.test.ScrollerTest + */ +public class ImageScroller extends Scroller { + private Image image; + private ScrollerImageCanvas canvas; + + public ImageScroller(Image image) { + viewport.setLayout(new BorderLayout()); + setImage(image); + } + public void resetImage(Image image) { + viewport.remove(canvas); + setImage(image); + invalidate(); + validate(); + } + public void scrollTo(int x, int y) { + Graphics g = canvas.getGraphics(); + if(g != null) { + g.translate(-x,-y); + g.drawImage(image, 0, 0, this); + } + } + public Dimension getScrollAreaSize() { + return new Dimension(image.getWidth(this), + image.getHeight(this)); + } + private void setImage(Image image) { + this.image = image; + hbar.setValue(0); + vbar.setValue(0); + viewport.add("Center", + canvas = new ScrollerImageCanvas(this, image)); + } +} + +class ScrollerImageCanvas extends ImageCanvas { + private ImageScroller scroller; + + public ScrollerImageCanvas(ImageScroller scroller, + Image image) { + super(image); + this.scroller = scroller; + } + public void paint(Graphics g) { + scroller.repaint(); + } +} diff --git a/java/gjt/LabelCanvas.java b/java/gjt/LabelCanvas.java new file mode 100644 index 00000000000..ba733249b76 --- /dev/null +++ b/java/gjt/LabelCanvas.java @@ -0,0 +1,93 @@ +package gjt; + +import java.awt.*; + +/** + * A selectable label. Clients can set the insets around the + * label via setInsets(Insets). + * + * LabelCanvases generate SelectionEvents when they are + * selected or deselected.<p> + * + * @version 1.0, Apr 1 1996 + * @author David Geary + * @see SelectionEvent + * @see gjt.test.LabelCanvasTest + */ +public class LabelCanvas extends Canvas { + private String label; + private boolean selected = false; + private Insets insets = new Insets(2,2,2,2); + private Point labelLoc = new Point(0,0); + + public LabelCanvas(String label) { + this.label = label; + } + public void paint(Graphics g) { + if(selected == true) paintSelected(g); + else + g.drawString(label, labelLoc.x, labelLoc.y); + } + public void setInsets(Insets insets) { + this.insets = insets; + repaint(); + } + public String getLabel () { return label; } + public boolean isSelected() { return selected; } + public void select () { selected = true; repaint(); } + public void deselect () { selected = false; repaint(); } + + public void resize(int w, int h) { + reshape(location().x, location().y, w, h); + } + public void reshape(int x, int y, int w, int h) { + super.reshape(x, y, w, h); + labelLoc = labelLocation(getGraphics()); + } + public Dimension minimumSize() { + return preferredSize(); + } + public Dimension preferredSize() { + FontMetrics fm = getFontMetrics(getFont()); + return new Dimension( + insets.left + fm.stringWidth(label) + + insets.right, + insets.top + fm.getHeight() + + insets.bottom); + } + public boolean mouseDown(Event event, int x, int y) { + if(selected) deselect(); + else select (); + + int eventType = isSelected() ? + SelectionEvent.SELECT : + SelectionEvent.DESELECT; + + Event newEvent = new SelectionEvent(this, + event, + eventType); + deliverEvent(newEvent); + + return true; + } + protected void paintSelected(Graphics g) { + Point labelLoc = labelLocation(g); + + g.setColor(getForeground()); + g.fillRect(0,0,size().width,size().height); + g.setColor(getBackground()); + g.drawString(label, labelLoc.x, labelLoc.y); + } + protected String paramString() { + return super.paramString() + ",text=" + label; + } + private Point labelLocation(Graphics g) { + Dimension size = size(); + FontMetrics fm = g.getFontMetrics(); + + int x = (size.width/2) - (fm.stringWidth(label)/2); + int y = (size.height/2) + (fm.getAscent()/2) - + fm.getLeading(); + return new Point(x,y); + } +} diff --git a/java/gjt/MessageDialog.java b/java/gjt/MessageDialog.java new file mode 100644 index 00000000000..4b00bc7033f --- /dev/null +++ b/java/gjt/MessageDialog.java @@ -0,0 +1,77 @@ +package gjt; + +import java.awt.*; + +/** + * A dialog that displays a message and comes equipped with an + * Ok button with which the dialog is dismissed.<p> + * + * Note that there is only one MessageDialog, that gets + * reused. Clients must call getMessageDialog() in order to + * access the one and only MessageDialog.<p> + * + * <em>Note: The 1.0.2 version of the AWT seems to have + * introduced a bug that causes pack() to work incorrectly + * under Win95.</em> + * + * @version 1.0, Apr 1 1996 + * @author David Geary + * @see GJTDialog + * @see gjt.test.MessageDialogTest + * @see gjt.test.DialogTest + */ +public class MessageDialog extends GJTDialog { + static private MessageDialog _theMessageDialog; + + private Button okButton; + private String message; + private ButtonPanel buttonPanel = new ButtonPanel(); + + static public MessageDialog getMessageDialog(Frame frame, + DialogClient client, + String title, + String message) { + if(_theMessageDialog == null) + _theMessageDialog = new MessageDialog(frame, + client, + title, + message); + else { + _theMessageDialog.setClient (client); + _theMessageDialog.setTitle (title); + _theMessageDialog.setMessage(message); + } + return _theMessageDialog; + } + private MessageDialog(Frame frame, DialogClient client, + String title, String message) { + super(frame, title, client, true); + okButton = buttonPanel.add("Ok"); + + setLayout(new BorderLayout()); + add("Center", new MessagePanel(message)); + add("South", buttonPanel); + pack(); + } + public void show() { + okButton.requestFocus(); + super.show(); + } + public boolean action(Event event, Object what) { + hide(); + client.dialogDismissed(this); + return true; + } + private void setMessage(String message) { + this.message = message; + } +} + +class MessagePanel extends Panel { + public MessagePanel(String message) { + add("Center", new Label(message, Label.CENTER)); + } + public Insets insets() { + return new Insets(10,10,10,10); + } +} diff --git a/java/gjt/MouseController.java b/java/gjt/MouseController.java new file mode 100644 index 00000000000..f044adee5ba --- /dev/null +++ b/java/gjt/MouseController.java @@ -0,0 +1,32 @@ +package gjt; + +import java.awt.Event; + +/** + * An interface for handling mouse events.<p> + * + * Components delegate handling of mouse events to a + * MouseController derivation.<p> + * + * For instance:<p> + *<pre> + * mouseDown(Event event, int x, int y) { + * return controller.mouseDown(event,x,y); + * } + *</pre> + * @version 1.0, Apr 1 1996 + * @author David Geary + * @see ImageButton + * @see ImageButtonController + * @see SpringyImageButtonController + * @see StickyImageButtonController + */ +public interface MouseController { + public boolean mouseEnter(Event event, int x, int y); + public boolean mouseExit (Event event, int x, int y); + + public boolean mouseMove (Event event, int x, int y); + public boolean mouseDown (Event event, int x, int y); + public boolean mouseUp (Event event, int x, int y); + public boolean mouseDrag (Event event, int x, int y); +} diff --git a/java/gjt/Orientation.java b/java/gjt/Orientation.java new file mode 100644 index 00000000000..f83b27451da --- /dev/null +++ b/java/gjt/Orientation.java @@ -0,0 +1,87 @@ +package gjt; + +/** + * Constants for orientations (and alignments).<p> + * + * This class may not be instantiated. + * + * @version 1.0, Apr 11 1996 + * @author David Geary + */ +public class Orientation { + public static final Orientation BAD = new Orientation(); + public static final Orientation NORTH = new Orientation(); + public static final Orientation SOUTH = new Orientation(); + public static final Orientation EAST = new Orientation(); + public static final Orientation WEST = new Orientation(); + public static final Orientation CENTER = new Orientation(); + public static final Orientation TOP = new Orientation(); + public static final Orientation LEFT = new Orientation(); + public static final Orientation RIGHT = new Orientation(); + public static final Orientation BOTTOM = new Orientation(); + + public static final Orientation HORIZONTAL = + new Orientation(); + public static final Orientation VERTICAL = + new Orientation(); + + static public Orientation fromString(String s) { + Orientation o = BAD; + + if(s.equals("NORTH") || s.equals("north")) o = NORTH; + else if(s.equals("SOUTH") || s.equals("south")) + o = SOUTH; + else if(s.equals("EAST") || s.equals("east")) + o = EAST; + else if(s.equals("WEST") || s.equals("west")) + o = WEST; + else if(s.equals("CENTER") || s.equals("center")) + o = CENTER; + else if(s.equals("TOP") || s.equals("top")) + o = TOP; + else if(s.equals("LEFT") || s.equals("left")) + o = LEFT; + else if(s.equals("RIGHT") || s.equals("right")) + o = RIGHT; + else if(s.equals("BOTTOM") || s.equals("bottom")) + o = BOTTOM; + else if(s.equals("VERTICAL") || s.equals("vertical")) + o = VERTICAL; + else if(s.equals("HORIZONTAL") || + s.equals("horizontal")) + o = HORIZONTAL; + + return o; + } + public String toString() { + String s = new String(); + + if(this == Orientation.NORTH) + s = getClass().getName() + "=NORTH"; + else if(this == Orientation.SOUTH) + s = getClass().getName() + "=SOUTH"; + else if(this == Orientation.EAST) + s = getClass().getName() + "=EAST"; + else if(this == Orientation.WEST) + s = getClass().getName() + "=WEST"; + else if(this == Orientation.CENTER) + s = getClass().getName() + "=CENTER"; + else if(this == Orientation.TOP) + s = getClass().getName() + "=TOP"; + else if(this == Orientation.LEFT) + s = getClass().getName() + "=LEFT"; + else if(this == Orientation.RIGHT) + s = getClass().getName() + "=RIGHT"; + else if(this == Orientation.BOTTOM) + s = getClass().getName() + "=BOTTOM"; + else if(this == Orientation.HORIZONTAL) + s = getClass().getName() + "=HORIZONTAL"; + else if(this == Orientation.VERTICAL) + s = getClass().getName() + "=VERTICAL"; + else if(this == Orientation.BAD) + s = getClass().getName() + "=BAD"; + + return s; + } + private Orientation() { } // Defeat instantiation +} diff --git a/java/gjt/ProgressDialog.java b/java/gjt/ProgressDialog.java new file mode 100644 index 00000000000..de7d4be1674 --- /dev/null +++ b/java/gjt/ProgressDialog.java @@ -0,0 +1,67 @@ +package gjt; + +import java.awt.*; + +/** + * A dialog that uses a bargauge to indicate progress made on a + * task that presumably takes some time to complete. + * + * ProgressDialog implements the singleton pattern: clients + * may only access the one and only ProgressDialog through the + * static getProgressDialog() method.<p> + * + * <em>Note: The 1.0.2 version of the AWT has introduced a + * bug that breaks the ProgressDialog under Motif - the + * bargauge does not function. This worked fine in 1.0.1.<em> + * + * @version 1.0, Apr 1 1996 + * @author David Geary + * @see GJTDialog + * @see Bargauge + * @see gjt.test.DialogTest + */ +public class ProgressDialog extends GJTDialog { + static private ProgressDialog _theProgressDialog; + static private int _preferredWidth = 400; + static private int _preferredHeight = 75; + static private Color _color; + static private boolean _dialogUp; + + private Bargauge bargauge; + + static public ProgressDialog getProgressDialog( + Frame frame, + String title, + Color color){ + if(_theProgressDialog == null) + _theProgressDialog = new ProgressDialog(frame, + title, + color); + else { + _theProgressDialog.setTitle (title); + _theProgressDialog.reset (); + } + return _theProgressDialog; + } + private ProgressDialog(Frame frame, + String title, + Color color) { + super(frame, title, null, true); + setLayout(new BorderLayout()); + add("Center", bargauge = new Bargauge(color)); + pack(); + } + public void setPercentComplete(double percent) { + bargauge.setFillPercent(percent); + bargauge.fill(); + + if(percent == 100) + hide(); + } + public void reset() { + bargauge.setFillPercent(0); + } + public Dimension preferredSize() { + return new Dimension(_preferredWidth, _preferredHeight); + } +} diff --git a/java/gjt/QuestionDialog.java b/java/gjt/QuestionDialog.java new file mode 100644 index 00000000000..042b491e178 --- /dev/null +++ b/java/gjt/QuestionDialog.java @@ -0,0 +1,130 @@ +package gjt; + +import java.awt.*; + +/** + * A dialog that presents a prompt and a TextField into which + * a reply may be entered. Comes complete with an Ok button + * and a Cancel button, whose uses will be left to the + * imagination.<p> + * + * @version 1.0, Apr 1 1996 + * @author David Geary + * @see GJTDialog + * @see gjt.test.DialogTest + */ +public class QuestionDialog extends GJTDialog { + static private int _defaultTextFieldSize = 20; + private Button okButton; + private Button cancelButton; + private String question; + private TextField textField; + private boolean wasCancelled; + private ButtonPanel buttonPanel = new ButtonPanel(); + + public QuestionDialog(Frame frame, DialogClient client, + String title, String question, + String initialResponse) { + this(frame, client, title, question, initialResponse, + _defaultTextFieldSize); + } + public QuestionDialog(Frame frame, DialogClient client, + String title, String question) { + this(frame, client, title, + question, null, _defaultTextFieldSize); + } + public QuestionDialog(Frame frame, DialogClient client, + String title, String question, + int textFieldSize) { + this(frame, client, title, + question, null, textFieldSize); + } + public QuestionDialog(Frame frame, DialogClient client, + String title, String question, + String initialResponse, + int textFieldSize) { + super(frame, title, client, true); + + QuestionPanel questionPanel; + + okButton = buttonPanel.add("Ok"); + cancelButton = buttonPanel.add("Cancel"); + + setLayout(new BorderLayout()); + add("North", questionPanel = + new QuestionPanel(this, question, + initialResponse, textFieldSize)); + add("South", buttonPanel); + textField = questionPanel.getTextField(); + pack(); + } + public boolean action(Event event, Object what) { + if(event.target == cancelButton) wasCancelled = true; + else wasCancelled = false; + + hide(); + dispose(); + client.dialogDismissed(this); + return true; + } + public void show() { + textField.requestFocus(); + super.show(); + } + public void returnInTextField() { + okButton.requestFocus(); + } + public TextField getTextField() { + return textField; + } + public String getAnswer() { + return textField.getText(); + } + public boolean wasCancelled() { + return wasCancelled; + } + private void setQuestion(String question) { + this.question = question; + } +} + +class QuestionPanel extends Panel { + private TextField field; + private QuestionDialog dialog; + + public QuestionPanel(QuestionDialog dialog, + String question) { + this(dialog, question, null, 0); + } + public QuestionPanel(QuestionDialog dialog, String question, + int columns) { + this(dialog, question, null, columns); + } + public QuestionPanel(QuestionDialog dialog, String question, + String initialResponse, int cols) { + this.dialog = dialog; + setLayout(new RowLayout()); + add(new Label(question)); + + if(initialResponse != null) { + if(cols != 0) + add(field=new TextField(initialResponse, cols)); + else + add(field=new TextField(initialResponse)); + } + else { + if(cols != 0) add(field = new TextField(cols)); + else add(field = new TextField()); + } + } + public TextField getTextField() { + return field; + } + public boolean action(Event event, Object what) { + dialog.returnInTextField(); + return false; + } + public Insets insets() { + return new Insets(10,10,10,10); + } +} diff --git a/java/gjt/RadioImageButtonPanelController.java b/java/gjt/RadioImageButtonPanelController.java new file mode 100644 index 00000000000..8dc34d25bff --- /dev/null +++ b/java/gjt/RadioImageButtonPanelController.java @@ -0,0 +1,45 @@ +package gjt; + +import java.awt.Event; + +/** + * A controller for an ImageButtonPanel that ensures that only + * one ImageButton in its associated ImageButtonPanel is + * selected at a time.<p> + * + * @version 1.0, Apr 1 1996 + * @author David Geary + * @see ImageButtonPanelController + * @see ImageButton + * @see ImageButtonPanel + * @see gjt.test.ToolbarTest + */ +class RadioImageButtonPanelController + extends ImageButtonPanelController { + ImageButton down; + + public RadioImageButtonPanelController( + ImageButtonPanel panel) { + super(panel); + } + public boolean mouseDown(Event event, int x, int y) { + ImageButton button; + + if(event.target instanceof ImageButton) { + button = (ImageButton)event.target; + if(down == button) return false; + + if(down != null) + down.paintRaised(); + + down = button; + } + return false; + } + public boolean mouseUp(Event event, int x, int y) { + return false; + } + public boolean mouseDrag(Event event, int x, int y) { + return false; + } +} diff --git a/java/gjt/RowLayout.java b/java/gjt/RowLayout.java new file mode 100644 index 00000000000..eecd074c34f --- /dev/null +++ b/java/gjt/RowLayout.java @@ -0,0 +1,153 @@ +package gjt; + +import java.awt.*; + +/** + * RowLayout lays out components in a row. At construction + * time, both horizontal orientation and vertical orientation + * may be specified, along with the gap to use between + * components.<p> + * + * Horizontal orientation must be one of the following: + * <dl> + * <dd> LEFT + * <dd> CENTER + * <dd> RIGHT + * </dl> + * + * Vertical orientation must be one of the following: + * <dl> + * <dd> TOP + * <dd> CENTER + * <dd> BOTTOM + * </dl> + * + * @version 1.0, Apr 1 1996 + * @author David Geary + * @see ColumnLayout + * @see Orientation + */ +public class RowLayout implements LayoutManager { + static private int _defaultGap = 5; + + private int gap; + private Orientation verticalOrientation; + private Orientation horizontalOrientation; + + public RowLayout() { + this(Orientation.CENTER, + Orientation.CENTER, _defaultGap); + } + public RowLayout(int gap) { + this(Orientation.CENTER, Orientation.CENTER, gap); + } + public RowLayout(Orientation horizontalOrient, + Orientation verticalOrient) { + this(horizontalOrient, verticalOrient, _defaultGap); + } + public RowLayout(Orientation horizontalOrient, + Orientation verticalOrient, int gap) { + Assert.notFalse(gap >= 0); + Assert.notFalse( + horizontalOrient == Orientation.LEFT || + horizontalOrient == Orientation.CENTER || + horizontalOrient == Orientation.RIGHT); + Assert.notFalse( + verticalOrient == Orientation.TOP || + verticalOrient == Orientation.CENTER || + verticalOrient == Orientation.BOTTOM); + + this.gap = gap; + this.verticalOrientation = verticalOrient; + this.horizontalOrientation = horizontalOrient; + } + + public void addLayoutComponent(String name, Component comp) { + } + public void removeLayoutComponent(Component comp) { + } + + public Dimension preferredLayoutSize(Container target) { + Insets insets = target.insets(); + Dimension dim = new Dimension(0,0); + int ncomponents = target.countComponents(); + Component comp; + Dimension d; + + for (int i = 0 ; i < ncomponents ; i++) { + comp = target.getComponent(i); + + if(comp.isVisible()) { + d = comp.preferredSize(); + + dim.width += d.width; + dim.height = Math.max(d.height, dim.height); + + if(i > 0) dim.width += gap; + } + } + dim.width += insets.left + insets.right; + dim.height += insets.top + insets.bottom; + + return dim; + } + public Dimension minimumLayoutSize(Container target) { + Insets insets = target.insets(); + Dimension dim = new Dimension(0,0); + int ncomponents = target.countComponents(); + Component comp; + Dimension d; + + for (int i = 0 ; i < ncomponents ; i++) { + comp = target.getComponent(i); + + if(comp.isVisible()) { + d = comp.minimumSize(); + + dim.width += d.width; + dim.height = Math.max(d.height, dim.height); + + if(i > 0) dim.width += gap; + } + } + dim.width += insets.left + insets.right; + dim.height += insets.top + insets.bottom; + + return dim; + } + public void layoutContainer(Container target) { + Insets insets = target.insets(); + int ncomponents = target.countComponents(); + int top = 0; + int left = insets.left; + Dimension tps = target.preferredSize(); + Dimension targetSize = target.size(); + Component comp; + Dimension ps; + + if(horizontalOrientation == Orientation.CENTER) + left = left + (targetSize.width/2) - (tps.width/2); + if(horizontalOrientation == Orientation.RIGHT) + left = left + targetSize.width - tps.width; + + for (int i = 0 ; i < ncomponents ; i++) { + comp = target.getComponent(i); + + if(comp.isVisible()) { + ps = comp.preferredSize(); + + if(verticalOrientation == Orientation.CENTER) + top = (targetSize.height/2) - (ps.height/2); + else if(verticalOrientation == Orientation.TOP) + top = insets.top; + else if( + verticalOrientation == Orientation.BOTTOM) + top = targetSize.height - + ps.height - insets.bottom; + + comp.reshape(left,top,ps.width,ps.height); + left += ps.width + gap; + } + } + } +} diff --git a/java/gjt/Scroller.java b/java/gjt/Scroller.java new file mode 100644 index 00000000000..61d6e5f55e5 --- /dev/null +++ b/java/gjt/Scroller.java @@ -0,0 +1,154 @@ +package gjt; + +import java.awt.*; + +/** + * Each Scroller contains a Panel (viewport) and two Scrollbars + * (horizontal and vertical). Works in conjunction with a + * ScrollerLayout, that lays out the viewport and two + * scrollbars.<p> + * + * Subclasses must override:<p> + * <dl> + * <dd> abstract public void scrollTo(int x, int y) + * <dd> abstract public Dimension getScrollAreaSize() + * </dl> + * + * @version 1.0, Apr 1 1996 + * @author David Geary + * @see ComponentScroller + * @see ImageScroller + * @see ScrollerLayout + * @see gjt.test.ComponentScrollerTest + * @see gjt.test.ImageScrollerTest + */ +public abstract class Scroller extends Panel { + protected Panel viewport; + protected Scrollbar hbar, vbar; + + abstract public void scrollTo(int x, int y); + abstract public Dimension getScrollAreaSize(); + + public Scroller() { + setLayout(new ScrollerLayout(this)); + add("Scroll", viewport = new Panel()); + add("East", vbar = new Scrollbar(Scrollbar.VERTICAL)); + add("South",hbar = new Scrollbar(Scrollbar.HORIZONTAL)); + } + public Scrollbar getHorizontalScrollbar() {return hbar; } + public Scrollbar getVerticalScrollbar () {return vbar; } + public Panel getViewport () {return viewport;} + + public boolean handleEvent(Event event) { + boolean handledEvent; + + switch(event.id) { + case Event.SCROLL_LINE_UP: scrollLineUp(event); + break; + case Event.SCROLL_LINE_DOWN: scrollLineDown(event); + break; + case Event.SCROLL_PAGE_UP: scrollPageUp (event); + break; + case Event.SCROLL_PAGE_DOWN: scrollPageDown(event); + break; + case Event.SCROLL_ABSOLUTE: scrollAbsolute(event); + break; + } + handledEvent = event.id == Event.SCROLL_LINE_UP || + event.id == Event.SCROLL_LINE_DOWN || + event.id == Event.SCROLL_PAGE_UP || + event.id == Event.SCROLL_PAGE_DOWN || + event.id == Event.SCROLL_ABSOLUTE; + + if(handledEvent) return true; + else return super.handleEvent(event); + } + public void paint (Graphics g) { scroll(); } + public void update(Graphics g) { paint(g); } + + public void manageScrollbars() { + manageHorizontalScrollbar(); + manageVerticalScrollbar (); + } + protected void manageHorizontalScrollbar() { + Dimension size = size(); + Dimension scrollAreaSize = getScrollAreaSize(); + + if(vbar.isVisible()) + size.width -= vbar.size().width; + + if(scrollAreaSize.width > size.width) { + if( ! hbar.isVisible()) + hbar.show(); + } + else if(hbar.isVisible()) { + hbar.hide(); + hbar.setValue(0); + repaint(); + } + } + protected void manageVerticalScrollbar() { + Dimension size = size(); + Dimension scrollAreaSize = getScrollAreaSize(); + + if(hbar.isVisible()) + size.height -= hbar.size().height; + + if(scrollAreaSize.height > size.height) { + if( ! vbar.isVisible()) + vbar.show(); + } + else if(vbar.isVisible()) { + vbar.hide(); + vbar.setValue(0); + repaint(); + } + } + public void setScrollbarValues() { + if(hbar.isVisible()) setHorizontalScrollbarValues(); + if(vbar.isVisible()) setVerticalScrollbarValues(); + } + protected void setHorizontalScrollbarValues() { + Dimension vsize = viewport.size(); + Dimension scrollAreaSize = getScrollAreaSize(); + int max = scrollAreaSize.width - vsize.width; + + hbar.setValues(hbar.getValue(), // value + vsize.width, // amt visible/page + 0, // minimum + max); // maximum + + setHorizontalLineAndPageIncrements(); + } + protected void setVerticalScrollbarValues() { + Dimension vsize = viewport.size(); + Dimension scrollAreaSize = getScrollAreaSize(); + int max = scrollAreaSize.height - vsize.height; + + vbar.setValues(vbar.getValue(), // value + vsize.height, // amt visible/page + 0, // minimum + max); // maximum + + setVerticalLineAndPageIncrements(); + } + protected void scrollLineUp (Event event) { scroll(); } + protected void scrollLineDown(Event event) { scroll(); } + protected void scrollPageUp (Event event) { scroll(); } + protected void scrollPageDown(Event event) { scroll(); } + protected void scrollAbsolute(Event event) { scroll(); } + + protected void setHorizontalLineAndPageIncrements() { + Dimension size = getScrollAreaSize(); + hbar.setLineIncrement(size.width/10); + hbar.setPageIncrement(size.width/5); + } + protected void setVerticalLineAndPageIncrements() { + Dimension size = getScrollAreaSize(); + vbar.setLineIncrement(size.height/10); + vbar.setPageIncrement(size.height/5); + } + protected void scroll() { + scrollTo(hbar.getValue(), vbar.getValue()); + } +} diff --git a/java/gjt/ScrollerLayout.java b/java/gjt/ScrollerLayout.java new file mode 100644 index 00000000000..21012fd5688 --- /dev/null +++ b/java/gjt/ScrollerLayout.java @@ -0,0 +1,160 @@ +package gjt; + +import java.awt.*; + +/** + * Layout manager for a Scroller.<p> + * + * Lays out 3 Components: a horizontal scrollbar, a vertical + * scrollbar and a viewport (Panel).<p> + * + * Valid names/Component pairs that can be added via + * addLayoutComponent(String, Component):<p> + * <dl> + * <dd> "East" Scrollbar (vertical) + * <dd> "West" Scrollbar (vertical) + * <dd> "North" Scrollbar (horizontal) + * <dd> "South" Scrollbar (horizontal) + * <dd> "Scroll" Panel (viewport) + * </dl> + * + * @version 1.0, Apr 1 1996 + * @author David Geary + * @see Scroller + */ +public class ScrollerLayout implements LayoutManager { + private Scroller scroller; + private Scrollbar hbar, vbar; + private String hbarPosition, vbarPosition; + private Component viewport; + private int top, bottom, right, left; + + public ScrollerLayout(Scroller scroller) { + this.scroller = scroller; + } + + public void addLayoutComponent(String name, + Component comp) { + Assert.notFalse(comp != null); + + if(comp instanceof Scrollbar) { + Scrollbar sbar = (Scrollbar)comp; + + if(sbar.getOrientation() == Scrollbar.VERTICAL) { + Assert.notFalse("East".equals(name) == true || + "West".equals(name) == true); + vbar = sbar; + vbarPosition = name; + } + else { + Assert.notFalse("North".equals(name) == true || + "South".equals(name) == true); + hbar = sbar; + hbarPosition = name; + } + } + else { + Assert.notFalse("Scroll".equals(name) == true); + viewport = comp; + } + } + public void removeLayoutComponent(Component comp) { + if(comp == vbar) vbar = null; + if(comp == hbar) hbar = null; + if(comp == viewport) viewport = null; + } + public Dimension preferredLayoutSize(Container parent) { + Dimension dim = new Dimension(0,0); + + if(vbar != null && vbar.isVisible()) { + Dimension d = vbar.preferredSize(); + dim.width += d.width; + dim.height = d.height; + } + if(hbar != null && hbar.isVisible()) { + Dimension d = hbar.preferredSize(); + dim.width += d.width; + dim.height = Math.max(d.height, dim.height); + } + if(viewport != null && viewport.isVisible()) { + Dimension d = viewport.preferredSize(); + dim.width += d.width; + dim.height = Math.max(d.height, dim.height); + } + return dim; + } + public Dimension minimumLayoutSize(Container parent) { + Dimension dim = new Dimension(0,0); + + if(vbar != null && vbar.isVisible()) { + Dimension d = vbar.minimumSize(); + dim.width += d.width; + dim.height = d.height; + } + if(hbar != null && hbar.isVisible()) { + Dimension d = hbar.minimumSize(); + dim.width += d.width; + dim.height = Math.max(d.height, dim.height); + } + if(viewport != null && viewport.isVisible()) { + Dimension d = viewport.minimumSize(); + dim.width += d.width; + dim.height = Math.max(d.height, dim.height); + } + return dim; + } + public void layoutContainer(Container target) { + Insets insets = target.insets(); + Dimension targetSize = target.size(); + + top = insets.top; + bottom = targetSize.height - insets.bottom; + left = insets.left; + right = targetSize.width - insets.right; + + scroller.manageScrollbars(); + + reshapeHorizontalScrollbar(); + reshapeVerticalScrollbar (); + reshapeViewport (); + + scroller.setScrollbarValues(); + } + private void reshapeHorizontalScrollbar() { + if(hbar != null && hbar.isVisible()) { + if("North".equals(hbarPosition)) { + Dimension d = hbar.preferredSize(); + hbar.reshape(left, top, right - left, d.height); + top += d.height; + } + else { // South + Dimension d = hbar.preferredSize(); + hbar.reshape(left, bottom - d.height, + right - left,d.height); + bottom -= d.height; + } + } + } + private void reshapeVerticalScrollbar() { + if(hbar != null && vbar.isVisible()) { + if("East".equals(vbarPosition)) { + Dimension d = vbar.preferredSize(); + vbar.reshape(right - d.width, top, + d.width, bottom - top); + right -= d.width; + } + else { // West + Dimension d = vbar.preferredSize(); + vbar.reshape(left, top, + d.width, bottom - top); + left += d.width; + } + } + } + private void reshapeViewport() { + if(viewport != null && viewport.isVisible()) { + viewport.reshape(left, top, + right - left, bottom - top); + } + } +} diff --git a/java/gjt/SelectionEvent.java b/java/gjt/SelectionEvent.java new file mode 100644 index 00000000000..4bcab59cd0a --- /dev/null +++ b/java/gjt/SelectionEvent.java @@ -0,0 +1,82 @@ +package gjt; + +import java.awt.Event; + +/** + * An extension of java.awt.Event, specifically designed for + * selection events.<p> + * + * SelectionEvents are constructed with arguments:<p> + * <dl> + * <dd> The AWT event that triggered the image button event + * <dd> The id of the event. + * </dl> + * + * An SelectionEvent's id (the constructor's 3rd argument), + * must be one of the following:<p> + * <dl> + * <dd> SelectionEvent.SELECT + * <dd> SelectionEvent.DESELECT + * </dl> + * + * SelectionEvent has only a constructor and a paramString() + * method. Containers that contain objects which are capable + * of generating SelectionEvents should check the events + * like so: + * + * <pre> + * // handleEvent(Event) method of a container that + * // contain objects that generate SelectionEvents + * + * public boolean handleEvent(Event event) { + * if(event instanceof SelectionEvent) { + * SelectionEvent sevent = + * (SelectionEvent)event; + * + * if(sevent.isSelected()) { + * // do something for selection + * } + * else { + * // do something for deselection + * } + * } + * } + * </pre> + * + * @version 1.0, Apr 1 1996 + * @author David Geary + * @see LabelCanvas + * @see ImageButtonEvent + * @see gjt.test.LabelCanvasTest + */ +public class SelectionEvent extends Event { + public static final int SELECT = 1; + public static final int DESELECT = 2; + + private int eventType; + + public SelectionEvent(Object target, + Event event, + int type) { + super(target, event.when, event.id, event.x, event.y, + event.key, event.modifiers, event.arg); + + Assert.notFalse(type == SELECT || type == DESELECT); + + eventType = type; + id = -1; + } + public boolean isSelected() { + return eventType == SELECT; + } + protected String paramString() { + String typeString = new String(); + + if(eventType == SelectionEvent.SELECT) + typeString = "SELECT"; + else if(eventType == SelectionEvent.DESELECT) + typeString = "DESELECT"; + + return super.paramString() + typeString; + } +} diff --git a/java/gjt/Separator.java b/java/gjt/Separator.java new file mode 100644 index 00000000000..6bd610e1ad9 --- /dev/null +++ b/java/gjt/Separator.java @@ -0,0 +1,90 @@ +package gjt; + +import java.awt.*; + +/** + * A separator that is drawn either vertically or horizontally + * depending upon how it is laid out. Can be drawn either + * etched-in or etched-out, with varying thicknesses. Both + * thickness and etching are settable at construction time + * only.<p> + * + * Default thickness is 2 pixels and default etching is + * Etching.IN. Note that thicknesses greater than 4 loose the + * etching effect.<p> + * + * @version 1.0, Apr 1 1996 + * @author David Geary + * @see Etching + * @see gjt.test.SeparatorTest + */ +public class Separator extends Canvas { + static private Etching _defaultEtching = Etching.IN; + static private int _defaultThickness = 2; + + private Etching etching; + private int thickness; + + public Separator() { + this(_defaultThickness, _defaultEtching); + } + public Separator(int thickness) { + this(thickness, _defaultEtching); + } + public Separator(Etching etching) { + this(_defaultThickness, etching); + } + public Separator(int thickness, Etching etching) { + this.etching = etching; + this.thickness = thickness; + resize(thickness, thickness); + } + public Dimension minimumSize() { + return preferredSize(); + } + public Dimension preferredSize() { + return new Dimension(thickness, thickness); + } + public void paint(Graphics g) { + Dimension size = size(); + Color brighter = getBackground().brighter().brighter(); + Color darker = getBackground().darker().darker(); + + if(etching == Etching.IN) { + if(size.width > size.height) + paintHorizontal(g, size, darker, brighter); + else + paintVertical(g, size, darker, brighter); + } + else { + if(size.width > size.height) + paintHorizontal(g, size, brighter, darker); + else + paintVertical(g, size, brighter, darker); + } + } + public String paramString() { + Dimension size = size(); + Orientation orient = size.width > size.height ? + Orientation.HORIZONTAL : + Orientation.VERTICAL; + return super.paramString() + "thickness=" + + thickness + "," + etching + "," + orient; + } + private void paintHorizontal(Graphics g, Dimension size, + Color top, Color bottom) { + g.setColor(top); + g.fillRect(0, (size.height/2) - (thickness/2), + size.width, thickness/2); + g.setColor(bottom); + g.fillRect(0, size.height/2, size.width, thickness/2); + } + private void paintVertical(Graphics g, Dimension size, + Color left, Color right) { + g.setColor(left); + g.fillRect((size.width/2) - (thickness/2), + 0, thickness/2, size.height); + g.setColor(right); + g.fillRect(size.width/2, 0, thickness/2, size.height); + } +} diff --git a/java/gjt/SpringyImageButtonController.java b/java/gjt/SpringyImageButtonController.java new file mode 100644 index 00000000000..3559e040459 --- /dev/null +++ b/java/gjt/SpringyImageButtonController.java @@ -0,0 +1,54 @@ +package gjt; + +import java.awt.Event; +import java.awt.Graphics; + +/** + * An ImageButtonController that reacts to mouseDown/mouseUp + * events exactly as a java.awt.Button does.<p> + * + * @version 1.0, Apr 1 1996 + * @author David Geary + * @see ImageButton + * @see ImageButtonController + * @see StickyImageButtonController + */ +public class SpringyImageButtonController + extends ImageButtonController { + public SpringyImageButtonController(ImageButton ib) { + super(ib); + } + public boolean mouseDown(Event event, int x, int y) { + if(event.modifiers == 0) { + getButton().paintInset(); + armButton(event); + } + return false; + } + public boolean mouseUp(Event event, int x, int y) { + if(event.modifiers == 0) { + if(getButton().isRaised() == false) { + getButton().paintRaised(); + activateButton(event); + } + } + return false; + } + public boolean mouseDrag(Event event, int x, int y) { + if(event.modifiers == 0) { + if(getButton().isInside(x,y)) { + if(getButton().isRaised()) { + getButton().paintInset(); + armButton(event); + } + } + else { + if(getButton().isRaised() == false) { + getButton().paintRaised(); + disarmButton(event); + } + } + } + return false; + } +} diff --git a/java/gjt/StateButton.java b/java/gjt/StateButton.java new file mode 100644 index 00000000000..6de20a76f98 --- /dev/null +++ b/java/gjt/StateButton.java @@ -0,0 +1,45 @@ +package gjt; + +import java.awt.Image; + +/** + * An ImageButton that cycles through a series of images. The + * image advances to the next image in the series every time + * the button is activated.<p> + * + * Note that the cycling is actually performed by the buttons' + * controller - a StateButtonController.<p> + * + * @version 1.0, Apr 1 1996 + * @author David Geary + * @see ImageButton + * @see StateButtonController + * @see gjt.test.StateButtonTest + */ +public class StateButton extends ImageButton { + private Image[] images; + private int state = 0; + private int numStates; + + public StateButton(Image[] images) { + super(images[0]); + + this.images = images; + numStates = images.length; + setController(new StateButtonController(this)); + waitForImages(); + } + public Image nextImage() { + if(state + 1 < numStates) state++; + else state = 0; + + return images[state]; + } + public int state() { + return state; + } + private void waitForImages() { + for(int i=0; i < images.length; ++i) + Util.waitForImage(this, images[i]); + } +} diff --git a/java/gjt/StateButtonController.java b/java/gjt/StateButtonController.java new file mode 100644 index 00000000000..d6fc83830a6 --- /dev/null +++ b/java/gjt/StateButtonController.java @@ -0,0 +1,27 @@ +package gjt; + +import java.awt.Event; + +/** + * A controller for a StateButton, that cycles through a + * series of images which reside in the StateButton class. + * Each time a mouse up is detected in the StateButton, the + * buttons image is set to the next image in the array. + * + * @version 1.0, Apr 1 1996 + * @author David Geary + * @see StateButton + * @see SpringyImageButtonController + * @see gjt.test.StateButtonTest + */ +class StateButtonController extends SpringyImageButtonController { + public StateButtonController(StateButton button) { + super(button); + } + public boolean mouseUp(Event event, int x, int y) { + StateButton button = (StateButton)getButton(); + button.setImage(button.nextImage()); + activateButton(event); + return super.mouseUp(event, x, y); + } +} diff --git a/java/gjt/StickyImageButtonController.java b/java/gjt/StickyImageButtonController.java new file mode 100644 index 00000000000..c459e5cdae1 --- /dev/null +++ b/java/gjt/StickyImageButtonController.java @@ -0,0 +1,87 @@ +package gjt; + +import java.awt.Event; +import java.awt.Graphics; + +/** + * An ImageButtonController that causes its associated + * ImageButton to "stick" when activated. If the ImageButton + * is raised it depresses<b>[1]</b> upon a mouse down and stays + * down upon a subsequent mouse up event. The same "sticky" + * behaviour occurs when a depressed ImageButton encounters a + * mouse down followed by a subsequent mouse up.<p> + * + * Note that false is returned from mouse event handlers; + * therefore mouse events will be propagated to the + * ImageButton's container. While this is not always + * desirable, it was deemed a better default than swallowing + * the event here. Subclasses may, of course, modify this + * behavior.<p> + * + * <b>[1]</b> No psychiatric consultation is necessary.<p> + * + * @version 1.0, Apr 1 1996 + * @author David Geary + * @see ImageButton + * @see ImageButtonController + * @see SpringyImageButtonController + */ +public class StickyImageButtonController + extends ImageButtonController { + private boolean buttonUpOnLastMouseDown = true; + + public StickyImageButtonController(ImageButton ib) { + super(ib); + } + public boolean mouseDown(Event event, int x, int y) { + ImageButton button = getButton(); + + if(event.modifiers == 0) { + if(button.isRaised()) button.paintInset(); + else button.paintRaised(); + + buttonUpOnLastMouseDown = getButton().isRaised(); + armButton(event); + } + return false; + } + public boolean mouseUp(Event event, int x, int y) { + activateButton(event); + return false; + } + public boolean mouseDrag(Event event, int x, int y) { + ImageButton button = getButton(); + + if(event.modifiers == 0) { + if(button.isInside(x,y)) { + if(buttonUpOnLastMouseDown) { + if(button.isRaised() == false) { + button.paintRaised(); + armButton(event); + } + } + else { + if(button.isRaised()) { + button.paintInset(); + armButton(event); + } + } + } + else { + if(buttonUpOnLastMouseDown) { + if(button.isRaised()) { + button.paintInset(); + disarmButton(event); + } + } + else { + if(button.isRaised() == false) { + button.paintRaised(); + disarmButton(event); + } + } + } + } + return false; + } +} diff --git a/java/gjt/Stopwatch.java b/java/gjt/Stopwatch.java new file mode 100644 index 00000000000..fc8963e88a1 --- /dev/null +++ b/java/gjt/Stopwatch.java @@ -0,0 +1,94 @@ +package gjt; + +import java.awt.*; + +/** + * A Thread that acts as a stopwatch.<p> + * + * Stopwatch starts running when it is constructed, and may be + * reset by the reset() method. getHour(), getMinute(), + * getSecond(), and getMillisecond() are used to get the + * elapsed time since construction, or since the last reset.<p> + * + * toString() returns the elapsed time in the form of + * HH:MM:SS:mm, where HH == hours, MM == minutes, SS == seconds + * and mm == milliseconds.<p> + * + * Each Stopwatch may have a StopwatchClient associated with it. + * If the StopwatchClient is non-null, the StopwatchClients' + * tick() method is invoked every 50 milliseconds.<p> + * + * @version 1.0, Apr 21 1996 + * @author David Geary + * @see StopwatchClient + * @see gjt.animation.Sequence + * @see gjt.animation.Sprite + */ +public class Stopwatch extends Thread { + private StopwatchClient client; + private long start, now, elapsed; + private long hour, minute, second, millisecond; + + public Stopwatch() { + this(null); + } + public Stopwatch(StopwatchClient client) { + start = System.currentTimeMillis(); + this.client = client; + } + public void update() { + now = System.currentTimeMillis(); + elapsed = now - start; + hour = minute = second = millisecond = 0; + + second = elapsed / 1000; + millisecond = elapsed % 1000; + millisecond = (millisecond == 0) ? 0 : millisecond/10; + + if(second > 59) { + minute = second / 60; + second = second - (minute*60); + } + if(minute > 59) { + hour = minute / 60; + minute = minute - (hour*60); + } + } + public String toString() { + update(); + return new String(stringValueOf(hour) + ":" + + stringValueOf(minute) + ":" + + stringValueOf(second) + ":" + + stringValueOf(millisecond)); + } + public long getHour () { return hour; } + public long getMinute () { return minute; } + public long getSecond () { return second; } + public long getMillisecond () { return millisecond; } + + public long elapsedTime() { + update(); + return elapsed; + } + public void reset() { + start = System.currentTimeMillis(); + } + public void run() { + while(true) { + try { + Thread.currentThread().sleep(50, 0); + update(); + if(client != null) + client.tick(); + } + catch(InterruptedException e) { + Assert.notFalse(false); + } + } + } + private String stringValueOf(long l) { + if(l < 10) return "0" + String.valueOf(l); + else return String.valueOf(l); + + } +} diff --git a/java/gjt/StopwatchClient.java b/java/gjt/StopwatchClient.java new file mode 100644 index 00000000000..c2eb5fb0460 --- /dev/null +++ b/java/gjt/StopwatchClient.java @@ -0,0 +1,14 @@ +package gjt; + +/** + * Client of a Stopwatch. Stopwatches that have non-null + * clients, call their clients' tick() method every 50 + * milliseconds.<p> + * + * @version 1.0, Apr 21 1996 + * @author David Geary + * @see Stopwatch + */ +public interface StopwatchClient { + public void tick(); +} diff --git a/java/gjt/ThreeDBorder.java b/java/gjt/ThreeDBorder.java new file mode 100644 index 00000000000..0441fdf3052 --- /dev/null +++ b/java/gjt/ThreeDBorder.java @@ -0,0 +1,53 @@ +package gjt; + +import java.awt.*; + +/** + * Extension of Border that draws a 3D border. + * + * Drawn raised by default, drawing style used by paint() is + * controlled by raise() and inset(). Note that raise() and + * inset() do not result in anything being painted, but only set + * the state for the next call to paint(). To set the state and + * paint in one operation, use paintRaised() and paintInset(). + * <p> + * + * The current state of the border may be obtained by calling + * isRaised().<p> + * + * @version 1.0, Apr 1 1996 + * @author David Geary + * @see Border + * @see EtchedRectangle + * @see gjt.test.BorderTest + */ +public class ThreeDBorder extends Border { + public ThreeDBorder(Component borderMe) { + this(borderMe, _defaultThickness, _defaultGap); + } + public ThreeDBorder(Component borderMe, + int borderThickness) { + this(borderMe, borderThickness, _defaultGap); + } + public ThreeDBorder(Component borderMe, + int borderThickness, int gap) { + super(borderMe, borderThickness, gap); + } + public void inset() { ((ThreeDRectangle)border()).inset(); } + public void raise() { ((ThreeDRectangle)border()).raise(); } + + public void paintRaised() { + ((ThreeDRectangle)border()).paintRaised(); + } + public void paintInset() { + ((ThreeDRectangle)border()).paintInset (); + } + public boolean isRaised() { + return ((ThreeDRectangle)border()).isRaised(); + } + protected DrawnRectangle border() { + if(border == null) + border = new ThreeDRectangle(this, thickness); + return border; + } +} diff --git a/java/gjt/ThreeDBorderStyle.java b/java/gjt/ThreeDBorderStyle.java new file mode 100644 index 00000000000..b0e1b7d8ab8 --- /dev/null +++ b/java/gjt/ThreeDBorderStyle.java @@ -0,0 +1,24 @@ +package gjt; + +/** + * Constants for 3D border styles. + * + * This class may not be instantiated. + * + * @version 1.0, Apr 11 1996 + * @author David Geary + */ +public class ThreeDBorderStyle { + public static final ThreeDBorderStyle RAISED = + new ThreeDBorderStyle(); + public static final ThreeDBorderStyle INSET = + new ThreeDBorderStyle(); + + public String toString() { + if(this == ThreeDBorderStyle.RAISED) + return getClass().getName() + "=RAISED"; + else + return getClass().getName() + "=INSET"; + } + private ThreeDBorderStyle() { } // defeat instantiation +} diff --git a/java/gjt/ThreeDRectangle.java b/java/gjt/ThreeDRectangle.java new file mode 100644 index 00000000000..647129190c5 --- /dev/null +++ b/java/gjt/ThreeDRectangle.java @@ -0,0 +1,105 @@ +package gjt; + +import java.awt.*; + +/** + * A DrawnRectangle which draws in 3D.<p> + * + * Drawn raised by default, drawing style used by paint() is + * controlled by raise() and inset(). Note that raise() and + * inset() do not result in anything being painted, but only set + * the state for the next call to paint(). To set the state and + * paint in one operation, use paintRaised() and paintInset(). + * <p> + * + * The current state of the rectangle may be obtained by + * calling isRaised().<p> + * + * @version 1.0, Apr 1 1996 + * @author David Geary + * @see DrawnRectangle + * @see EtchedRectangle + * @see gjt.test.DrawnRectangleTest + */ +public class ThreeDRectangle extends DrawnRectangle { + protected static ThreeDBorderStyle + _defaultState = ThreeDBorderStyle.RAISED; + + private ThreeDBorderStyle state; + + public ThreeDRectangle(Component drawInto) { + this(drawInto, _defaultState, + _defaultThickness, 0, 0, 0, 0); + } + public ThreeDRectangle(Component drawInto, int thickness) { + this(drawInto, _defaultState, thickness, 0, 0, 0, 0); + } + public ThreeDRectangle(Component drawInto, + int x, int y, int w, int h) { + this(drawInto, + _defaultState, _defaultThickness, x, y, w, h); + } + public ThreeDRectangle(Component drawInto, int thickness, + int x, int y, + int w, int h) { + this(drawInto, _defaultState, thickness, x, y, w, h); + } + public ThreeDRectangle(Component drawInto, + ThreeDBorderStyle state, + int thickness, int x, int y, + int w, int h) { + super(drawInto, thickness, x, y, w, h); + this.state = state; + } + public void paint() { + if(state == ThreeDBorderStyle.RAISED) paintRaised(); + else paintInset (); + } + public void raise() { state = ThreeDBorderStyle.RAISED; } + public void inset() { state = ThreeDBorderStyle.INSET; } + + public boolean isRaised() { + return state == ThreeDBorderStyle.RAISED; + } + public String paramString() { + return super.paramString() + "," + state; + } + public void paintRaised() { + Graphics g = drawInto.getGraphics(); + + if(g != null) { + raise (); + drawTopLeftLines (g, brighter()); + drawBottomRightLines(g, getLineColor()); + } + } + public void paintInset() { + Graphics g = drawInto.getGraphics(); + + if(g != null) { + inset (); + drawTopLeftLines (g, getLineColor()); + drawBottomRightLines(g, brighter()); + } + } + private void drawTopLeftLines(Graphics g, Color color) { + int thick = getThickness(); + g.setColor(color); + + for(int i=0; i < thick; ++i) { + g.drawLine(x+i, y+i, x + width-(i+1), y+i); + g.drawLine(x+i, y+i+1, x+i, y + height-(i+1)); + } + } + private void drawBottomRightLines(Graphics g, Color color) { + int thick = getThickness(); + g.setColor(color); + + for(int i=1; i <= thick; ++i) { + g.drawLine(x+i-1, y + height-i, + x + width-i, y + height-i); + g.drawLine(x + width-i, y+i-1, + x + width-i, y + height-i); + } + } +} diff --git a/java/gjt/Toolbar.java b/java/gjt/Toolbar.java new file mode 100644 index 00000000000..4d6ebddc217 --- /dev/null +++ b/java/gjt/Toolbar.java @@ -0,0 +1,58 @@ +package gjt; + +import java.awt.*; + +/** + * A toolbar containing image buttons which are laid out to the + * north of (horizontal) separator.<p> + * + * @version 1.0, Apr 1 1996 + * @author David Geary + * @see ImageButton + * @see ImageButtonPanel + * @see gjt.test.ToolbarTest + */ +public class Toolbar extends Panel { + static private int _defaultGap = 0; + static private int _defaultLeftInset = 0; + + private ToolbarButtonPanel buttonPanel; + + public Toolbar() { + this(_defaultLeftInset, _defaultGap); + } + public Toolbar(int leftInset, int gap) { + buttonPanel = new ToolbarButtonPanel(leftInset, gap); + + setLayout(new BorderLayout()); + add ("North", buttonPanel); + add ("South", new Separator()); + } + public ImageButton add(Image image) { + return buttonPanel.add(image); + } + public void add(ImageButton button) { + buttonPanel.add(button); + } + public void addSpacer(int sizeInPixels) { + Assert.notFalse(sizeInPixels > 0); + buttonPanel.addSpacer(sizeInPixels); + } +} + +class ToolbarButtonPanel extends ImageButtonPanel { + private int leftInset; + + public ToolbarButtonPanel(int leftInset, int gap) { + super(Orientation.HORIZONTAL, + Orientation.LEFT, + Orientation.CENTER, + gap); + + this.leftInset = leftInset; + setController(null); + } + public Insets insets() { + return new Insets(5,leftInset,5,5); + } +} diff --git a/java/gjt/Util.java b/java/gjt/Util.java new file mode 100644 index 00000000000..0970a6fd488 --- /dev/null +++ b/java/gjt/Util.java @@ -0,0 +1,69 @@ +package gjt; + +import java.applet.Applet; +import java.awt.*; + +/** + * A handy collection of methods for getting a component's + * frame, getting a component's applet, waiting for a + * component's image, and wallpapering a components background. + * <p> + * + * @version 1.0, Apr 1 1996 + * @author David Geary + */ +public class Util { + public static Frame getFrame(Component component) { + Component c = component; + + if(c instanceof Frame) + return (Frame)c; + + while((c = c.getParent()) != null) { + if(c instanceof Frame) + return (Frame)c; + } + return null; + } + public static Applet getApplet(Component component) { + Component c = component; + + if(c instanceof Applet) + return (Applet)c; + + while((c = c.getParent()) != null) { + if(c instanceof Applet) + return (Applet)c; + } + return null; + } + public static void waitForImage(Component component, + Image image) { + MediaTracker tracker = new MediaTracker(component); + try { + tracker.addImage(image, 0); + tracker.waitForID(0); + } + catch(InterruptedException e) { Assert.notNull(null); } + } + public static void wallPaper(Component component, + Graphics g, + Image image) { + Dimension compsize = component.size(); + Util.waitForImage(component, image); + + int patchW = image.getWidth(component); + int patchH = image.getHeight(component); + + Assert.notFalse(patchW != -1 && patchH != -1); + + for(int r=0; r < compsize.width; r += patchW) { + for(int c=0; c < compsize.height; c += patchH) + g.drawImage(image, r, c, component); + } + } + public static void setCursor(int cursor, + Component component) { + getFrame(component).setCursor(cursor); + } +} diff --git a/java/gjt/YesNoDialog.java b/java/gjt/YesNoDialog.java new file mode 100644 index 00000000000..2db64ea6e4b --- /dev/null +++ b/java/gjt/YesNoDialog.java @@ -0,0 +1,80 @@ +package gjt; + +import java.awt.*; + +/** + * Similar in fuction to the MessageDialog, YesNoDialog poses + * a question, that is answered by selection of either a Yes + * button or a No button.<p> + * + * Note that the YesNoDialog is a singleton - meaning there is + * only one YesNoDialog in existence per applet. Clients + * may obtain the YesNoDialog by invoking getYesNoDialog().<p> + * + * @version 1.0, Apr 1 1996 + * @author David Geary + * @see GJTDialog + * @see MessageDialog + * @see gjt.test.DialogTest + */ +public class YesNoDialog extends GJTDialog { + static private YesNoDialog _theYesNoDialog; + private Button yesButton; + private Button noButton; + private String message; + private boolean answer = false; + private ButtonPanel buttonPanel = new ButtonPanel(); + + static public YesNoDialog getYesNoDialog( Frame frame, + DialogClient client, + String title, + String message) { + if(_theYesNoDialog == null) + _theYesNoDialog = new YesNoDialog(frame,client, + title,message); + else { + _theYesNoDialog.setClient (client); + _theYesNoDialog.setTitle (title); + _theYesNoDialog.setMessage(message); + } + return _theYesNoDialog; + } + private YesNoDialog(Frame frame, DialogClient client, + String title, String message) { + super(frame, title, client, true); + yesButton = buttonPanel.add("Yes"); + noButton = buttonPanel.add("No"); + + setLayout(new BorderLayout()); + add("Center", new YesNoPanel(message)); + add("South", buttonPanel); + pack(); + } + public void show() { + yesButton.requestFocus(); + super.show(); + } + public boolean answeredYes() { + return answer; + } + public boolean action(Event event, Object what) { + if(event.target == yesButton) answer = true; + else answer = false; + + hide(); + client.dialogDismissed(this); + return true; + } + private void setMessage(String message) { + this.message = message; + } +} + +class YesNoPanel extends Panel { + public YesNoPanel(String question) { + add("Center", new Label(question, Label.CENTER)); + } + public Insets insets() { + return new Insets(10,10,10,10); + } +} diff --git a/java/gjt/animation/CollisionArena.java b/java/gjt/animation/CollisionArena.java new file mode 100644 index 00000000000..defb1a6d86b --- /dev/null +++ b/java/gjt/animation/CollisionArena.java @@ -0,0 +1,39 @@ +package gjt.animation; + +import java.awt.Dimension; +import java.awt.Insets; +import java.util.Vector; +import gjt.Orientation; + +/** + * A CollisionArena is defined as an arena in which collisions + * may take place.<p> + * + * CollisionArenas must be able to report their size and + * insets, and return a Vector of the Sprites contained in the + * arena.<p> + * + * CollisionArenas must also implement two methods for handling + * sprite and edge collisions, respectively. + * + * @version 1.0, Apr 1 1996 + * @author David Geary + * @see Playfield + * @see CollisionDetector + * @see EdgeCollisionDetector + * @see SpriteCollisionDetector + * @see gjt.test.SimpleAnimationTest + * @see gjt.test.BumpAnimationTest + * @see gjt.test.TwoDrinkersAnimationTest + */ +public interface CollisionArena { + abstract public Vector getSprites(); + abstract public Dimension getSize (); + abstract public Insets getInsets (); + + abstract public void spriteCollision(Sprite sprite, + Sprite other); + + abstract public void edgeCollision(Sprite sprite, + Orientation orient); +} diff --git a/java/gjt/animation/CollisionDetector.java b/java/gjt/animation/CollisionDetector.java new file mode 100644 index 00000000000..ff05f16c6d3 --- /dev/null +++ b/java/gjt/animation/CollisionDetector.java @@ -0,0 +1,24 @@ +package gjt.animation; + +/** + * Collision detectors detect collisions that take place within + * a CollisionArena. + * + * @version 1.0, Apr 1 1996 + * @author David Geary + * @see CollisionArena + * @see EdgeCollisionDetector + * @see SpriteCollisionDetector + * @see gjt.test.SimpleAnimationTest + * @see gjt.test.BumpAnimationTest + * @see gjt.test.TwoDrinkersAnimationTest + */ +abstract public class CollisionDetector { + protected CollisionArena arena; + + abstract public void detectCollisions(); + + public CollisionDetector(CollisionArena arena) { + this.arena = arena; + } +} diff --git a/java/gjt/animation/EdgeCollisionDetector.java b/java/gjt/animation/EdgeCollisionDetector.java new file mode 100644 index 00000000000..8624b7c2f28 --- /dev/null +++ b/java/gjt/animation/EdgeCollisionDetector.java @@ -0,0 +1,53 @@ +package gjt.animation; + +import java.awt.*; +import java.util.Enumeration; +import java.util.Vector; +import gjt.Orientation; + +/** + * A CollisionDetector that detects collisions between Sprites + * and the edges of the CollisionArena in which they reside.<p> + * + * @version 1.0, Apr 1 1996 + * @author David Geary + * @see CollisionDetector + * @see Sprite + * @see gjt.test.SimpleAnimationTest + * @see gjt.test.BumpAnimationTest + * @see gjt.test.TwoDrinkersAnimationTest + */ +public class EdgeCollisionDetector extends CollisionDetector { + public EdgeCollisionDetector(CollisionArena arena) { + super(arena); + } + public void detectCollisions() { + Enumeration sprites = arena.getSprites().elements(); + Dimension arenaSize = arena.getSize(); + Insets arenaInsets = arena.getInsets(); + Sprite sprite; + + while(sprites.hasMoreElements()) { + sprite = (Sprite)sprites.nextElement(); + + Point nl = sprite.nextLocation (); + Point mv = sprite.getMoveVector(); + int nextRightEdge = nl.x + sprite.width(); + int nextBottomEdge = nl.y + sprite.height(); + int arenaBottomEdge = arenaSize.height - + arenaInsets.bottom; + int arenaRightEdge = arenaSize.width - + arenaInsets.right; + + if(nextRightEdge > arenaRightEdge) + arena.edgeCollision(sprite, Orientation.LEFT); + else if(nl.x < arenaInsets.left) + arena.edgeCollision(sprite, Orientation.RIGHT); + + if(nextBottomEdge > arenaBottomEdge) + arena.edgeCollision(sprite, Orientation.BOTTOM); + else if(nl.y < arenaInsets.top) + arena.edgeCollision(sprite, Orientation.TOP); + } + } +} diff --git a/java/gjt/animation/Playfield.java b/java/gjt/animation/Playfield.java new file mode 100644 index 00000000000..386c0fb24c4 --- /dev/null +++ b/java/gjt/animation/Playfield.java @@ -0,0 +1,140 @@ +package gjt.animation; + +import java.awt.*; +import java.util.Enumeration; +import java.util.Vector; +import gjt.Util; + +/** + * A surface upon which Sprites are animated. Playfields are + * responsible for animating the sprites.<p> + * + * Each Playfield comes complete with two collision detectors: + * an edge collision detector and a sprite collision detector. + * + * Playfield is an abstract class: extensions must implement + * the following methods: + * <dl> + * <dd> void paintBackground(Graphics) + * <dd> void void spriteCollision(Sprite sprite, Sprite other) + * <dd> void void edgeCollision (Sprite sprite, Sprite other) + * </dl> + * + * @version 1.0, Apr 1 1996 + * @author David Geary + * @see CollisionArena + * @see Sprite + * @see SpriteCollisionDetector + * @see EdgeCollisionDetector + * @see gjt.test.SimpleAnimationTest + * @see gjt.test.BumpAnimationTest + * @see gjt.test.TwoDrinkersAnimationTest + */ +public abstract class Playfield extends Canvas + implements Runnable, + CollisionArena { + protected Vector sprites = new Vector(); + private boolean running = false; + private Insets insets = new Insets(0,0,0,0); + + private Thread animationThread; + private Image bgoffscreen, + workplaceBuffer; + private Dimension offscreenSize; + private EdgeCollisionDetector edgeCollisionDetector; + private SpriteCollisionDetector spriteCollisionDetector; + + abstract public void paintBackground(Graphics g); + + public Playfield() { + edgeCollisionDetector = + new EdgeCollisionDetector(this); + spriteCollisionDetector = + new SpriteCollisionDetector(this); + } + public void stop () { running = false; } + public boolean running () { return running; } + public Dimension getSize () { return size(); } + public Insets getInsets () { return insets; } + public Vector getSprites() { return sprites; } + + public void addSprite(Sprite sprite) { + sprites.addElement(sprite); + } + public void setInsets(Insets insets) { + this.insets = insets; + } + public void start() { + animationThread = new Thread(this); + running = true; + animationThread.start(); + } + public void paint(Graphics g) { + if(needNewOffscreenBuffer()) { + workplaceBuffer = createOffscreenImage(size()); + bgoffscreen = createOffscreenImage(size()); + paintBackground(bgoffscreen.getGraphics()); + } + g.drawImage(bgoffscreen, 0, 0, this); + paintSprites(); + } + public void reshape(int x, int y, int w, int h) { + super.reshape(x,y,w,h); + repaint(); + } + public void run() { + while(running == true) { + edgeCollisionDetector.detectCollisions (); + spriteCollisionDetector.detectCollisions(); + + animateSprites(); + Thread.currentThread().yield(); + } + animationThread = null; + } + private boolean needNewOffscreenBuffer() { + return (workplaceBuffer == null || + bgoffscreen == null || + size().width != offscreenSize.width || + size().height != offscreenSize.height); + } + private Image createOffscreenImage(Dimension size) { + Image image = createImage(size.width, size.height); + Util.waitForImage(this, image); + offscreenSize = size; + return image; + } + protected void animateSprites() { + Sprite nextSprite; + Enumeration e = sprites.elements(); + + while(e.hasMoreElements()) { + nextSprite = (Sprite)e.nextElement(); + nextSprite.animate(); + } + } + protected void paintSprites() { + Sprite nextSprite; + Enumeration e = sprites.elements(); + + while(e.hasMoreElements()) { + nextSprite = (Sprite)e.nextElement(); + paintSprite(nextSprite); + } + } + protected void paintSprite(Sprite sprite) { + Graphics g = getGraphics(); + Graphics wpg = workplaceBuffer.getGraphics(); + Rectangle clip = sprite.clipRect(); + + wpg.clipRect(clip.x, clip.y, clip.width, clip.height); + wpg.drawImage(bgoffscreen, 0, 0, this); + sprite.paint(wpg); + + g.clipRect (clip.x, clip.y, clip.width, clip.height); + g.drawImage(workplaceBuffer, 0, 0, this); + + g.dispose(); + wpg.dispose(); + } +} diff --git a/java/gjt/animation/Sequence.java b/java/gjt/animation/Sequence.java new file mode 100644 index 00000000000..7b777ecd0d8 --- /dev/null +++ b/java/gjt/animation/Sequence.java @@ -0,0 +1,119 @@ +package gjt.animation; + +import java.util.Vector; +import java.awt.*; +import java.awt.image.ImageObserver; +import gjt.Util; +import gjt.Stopwatch; + +/** + * A sequence of images used in an animation. Each sequence + * keeps track of the number of cycles the sequence is to run, + * and reports whether or not the cycles have been completed + * via the boolean animationOver() method. + * + * @version 1.0, Apr 1 1996 + * @author David Geary + * @see Sprite + * @see Playfield + * @see gjt.test.SimpleAnimationTest + * @see gjt.test.BumpAnimationTest + * @see gjt.test.TwoDrinkersAnimationTest + */ +public class Sequence { + private static long infiniteCycle = -1; + + private Vector cells = new Vector(); + private Point lastPaintLocation = new Point(0,0); + private Stopwatch cellAdvanceTimer = new Stopwatch(); + private Image currentImage, lastImagePainted; + private long cellAdvanceInterval = 0, + currentCycle = 0, + cyclesPerAnimation = 0; + + public Sequence() { } + + public Sequence(Component component, Image[] images) { + for(int i=0; i < images.length; ++i) { + addImage(component, images[i]); + } + cyclesPerAnimation = infiniteCycle; + } + public void start () { cellAdvanceTimer.start(); } + public Image getLastImage () { return lastImagePainted; } + public Point getLastLocation() { return lastPaintLocation; } + public int getNumImages () { return cells.size(); } + + public long getCurrentCycle() { return currentCycle; } + public void setCurrentCycle(long c) { currentCycle = c; } + + public long getCyclesPerAnimation() { + return currentCycle; + } + public void setCyclesPerAnimation(long cyclesPerAnimation) { + this.cyclesPerAnimation = cyclesPerAnimation; + } + public Image getFirstImage() { + return (Image)cells.firstElement(); + } + public Image getCurrentImage() { + return currentImage; + } + public int getCurrentImagePosition() { + return cells.indexOf(currentImage); + } + public Image getNextImage() { + int index = cells.indexOf(currentImage); + Image image; + + if(index == cells.size() - 1) + image = (Image)cells.elementAt(0); + else + image = (Image)cells.elementAt(index + 1); + + return image; + } + public void setAdvanceInterval(long interval) { + cellAdvanceInterval = interval; + } + public void addImage(Component component, Image image) { + if(currentImage == null) + currentImage = image; + + Util.waitForImage(component, image); + cells.addElement(image); + } + public void removeImage(Image image) { + cells.removeElement(image); + } + public boolean needsRepainting(Point point) { + return (lastPaintLocation.x != point.x || + lastPaintLocation.y != point.y || + lastImagePainted != currentImage); + } + public void paint(Graphics g, int x, int y, + ImageObserver observer) { + g.drawImage(currentImage, x, y, observer); + lastPaintLocation.x = x; + lastPaintLocation.y = y; + lastImagePainted = currentImage; + } + public boolean isAtLastImage() { + return getCurrentImagePosition() == (cells.size() - 1); + } + public boolean timeToAdvanceCell() { + return + cellAdvanceTimer.elapsedTime() > cellAdvanceInterval; + } + public boolean animationOver() { + return (cyclesPerAnimation != infiniteCycle) && + (currentCycle >= cyclesPerAnimation); + } + public void advance() { + if(isAtLastImage()) + ++currentCycle; + + currentImage = getNextImage(); + cellAdvanceTimer.reset(); + } +} diff --git a/java/gjt/animation/Sprite.java b/java/gjt/animation/Sprite.java new file mode 100644 index 00000000000..e7840b7615b --- /dev/null +++ b/java/gjt/animation/Sprite.java @@ -0,0 +1,191 @@ +package gjt.animation; + +import java.awt.*; +import java.util.Vector; +import gjt.Assert; +import gjt.Stopwatch; +import gjt.Util; + +/** + * A sequence of images which are animated and moved about on + * a Playfield.<p> + * + * Each Sprite is constructed with a reference to it's + * Playfield, a Sequence, and a beginning position for it's + * upper left hand corner.<p> + * + * A Sprite's animation is controlled by invoking the following + * methods: + *<dl> + *<dd> setMoveVector(Point) + *<dd> setMoveInterval(long) + *<dd> setImageChangeInterval(long) + *<dd> setMainSequence(Sequence) + *<dd> setSequence(Sequence) + *</dl> + * + * @version 1.0, Apr 1 1996 + * @author David Geary + * @see Sequence + * @see Playfield + * @see SpriteCollisionDetector + * @see gjt.test.SimpleAnimationTest + * @see gjt.test.BumpAnimationTest + * @see gjt.test.TwoDrinkersAnimationTest + */ +public class Sprite { + private Playfield field; + private Sequence currentSequence, mainSequence; + private Stopwatch moveTimer = new Stopwatch(); + + private Point ulhc = new Point(0,0); + private Point start = new Point(0,0); + private Point moveVector = new Point(1,1); + + private Rectangle clip = new Rectangle(0,0); + private Rectangle curBounds, lastBounds; + + private int width, height; + private long moveInterval = 0; + + public Sprite(Playfield field, + Sequence sequence, + Point ulhc) { + Assert.notNull(field); + Assert.notNull(sequence); + Assert.notNull(ulhc); + + this.field = field; + this.ulhc = ulhc; + start.x = ulhc.x; + start.y = ulhc.y; + + setSequence(sequence); + setMainSequence(sequence); + + initializeBounds(); + moveTimer.start(); + currentSequence.start(); + } + public Playfield getPlayfield() { return field; } + public Rectangle clipRect () { return clip; } + public Rectangle curBounds () { return curBounds; } + + public int width () { return width; } + public int height () { return height; } + public void reverseX () { moveVector.x = 0-moveVector.x; } + public void reverseY () { moveVector.y = 0-moveVector.y; } + public void reverse () { reverseX(); reverseY(); } + public Point start () { return start; } + + public void setMoveVector (Point p) { moveVector = p; } + public Point getMoveVector() { return moveVector; } + + public void play(Sequence sequence, long cycles) { + setSequence(sequence); + sequence.setCyclesPerAnimation(cycles); + sequence.setCurrentCycle(0); + } + public void animate() { + if(currentSequence.animationOver()) + currentSequence = mainSequence; + + if(timeToChangeImage()) currentSequence.advance(); + if(timeToMove()) move(); + if(needsRepainting()) field.paintSprite(this); + } + public void setMainSequence(Sequence sequence) { + mainSequence = sequence; + } + public Sequence getMainSequence() { + return mainSequence; + } + public void setSequence(Sequence sequence) { + currentSequence = sequence; + + if(curBounds != null) + updateBounds(); + } + public Sequence getSequence() { + return currentSequence; + } + public boolean intersects(Sprite otherSprite) { + return curBounds().intersects(otherSprite.curBounds()); + } + public boolean willIntersect(Sprite otherSprite) { + return + nextBounds().intersects(otherSprite.nextBounds()); + } + public boolean timeToMove() { + return moveTimer.elapsedTime() > moveInterval; + } + public boolean timeToChangeImage() { + return currentSequence.timeToAdvanceCell(); + } + public void moveTo(Point p) { + ulhc = p; + moveTimer.reset(); + } + public boolean needsRepainting() { + return currentSequence.needsRepainting(ulhc); + } + public void setMoveInterval(long interval) { + moveInterval = interval; + } + public void setImageChangeInterval(long interval) { + currentSequence.setAdvanceInterval(interval); + } + public void move() { + ulhc.x += moveVector.x; + ulhc.y += moveVector.y; + updateBounds(); + moveTimer.reset(); + } + public Point location() { + return ulhc; + } + public Point nextLocation() { + return new Point(ulhc.x + moveVector.x, + ulhc.y + moveVector.y); + } + public Rectangle nextBounds() { + Image nextImage = currentSequence.getNextImage(); + Point nextLoc = nextLocation(); + + return new Rectangle( + nextLoc.x, nextLoc.y, width, height); + } + public void paint(Graphics g) { + currentSequence.paint(g, ulhc.x, ulhc.y, field); + } + private void initializeBounds() { + Image curImage = currentSequence.getCurrentImage(); + + width = curImage.getWidth (field); + height = curImage.getHeight(field); + + curBounds = + new Rectangle(ulhc.x, ulhc.y, width, height); + + lastBounds = new Rectangle(curBounds.x, + curBounds.y, + curBounds.width, + curBounds.height); + + clip = lastBounds.union(curBounds); + } + private void updateBounds() { + Image curImage = currentSequence.getCurrentImage(); + + lastBounds.width = curBounds.width; + lastBounds.height = curBounds.height; + + curBounds.width = width = curImage.getWidth(field); + curBounds.height = height = curImage.getHeight(field); + + lastBounds.move(curBounds.x, curBounds.y); + curBounds.move (ulhc.x, ulhc.y); + + clip = lastBounds.union(curBounds); + } +} diff --git a/java/gjt/animation/SpriteCollisionDetector.java b/java/gjt/animation/SpriteCollisionDetector.java new file mode 100644 index 00000000000..2ef37d79208 --- /dev/null +++ b/java/gjt/animation/SpriteCollisionDetector.java @@ -0,0 +1,45 @@ +package gjt.animation; + +import java.awt.*; +import java.util.Enumeration; +import java.util.Vector; +import gjt.Orientation; + +/** + * A CollisionDetector that detects collisions between Sprites + * residing in a CollisionArena.<p> + * + * @version 1.0, Apr 1 1996 + * @author David Geary + * @see CollisionArena + * @see CollisionDetector + * @see Sprite + * @see gjt.test.SimpleAnimationTest + * @see gjt.test.BumpAnimationTest + * @see gjt.test.TwoDrinkersAnimationTest + */ +public class SpriteCollisionDetector extends CollisionDetector { + public SpriteCollisionDetector(CollisionArena arena) { + super(arena); + } + public void detectCollisions() { + Enumeration sprites = arena.getSprites().elements(); + Sprite sprite; + + while(sprites.hasMoreElements()) { + sprite = (Sprite)sprites.nextElement(); + + Enumeration otherSprites = + arena.getSprites().elements(); + Sprite otherSprite; + + while(otherSprites.hasMoreElements()) { + otherSprite=(Sprite)otherSprites.nextElement(); + + if(otherSprite != sprite) + if(sprite.willIntersect(otherSprite)) + arena.spriteCollision(sprite,otherSprite); + } + } + } +} diff --git a/java/gjt/image/BleachImageFilter.java b/java/gjt/image/BleachImageFilter.java new file mode 100644 index 00000000000..f698a218284 --- /dev/null +++ b/java/gjt/image/BleachImageFilter.java @@ -0,0 +1,53 @@ +package gjt.image; + +import java.awt.image.*; +import gjt.Assert; + +/** + * A derivation of RGBImageFilter that bleaches an image.<p> + * + * Extent of the bleaching effect is controlled by the only + * constructor argument: an integer representing the percentage + * of bleaching. The percentage of bleaching may also be + * controlled after instantiation by invoking the + * void percent(int) method.<p> + * + * @version 1.0, Apr 1 1996 + * @author David Geary + * @see RGBImageFilter + */ +public class BleachImageFilter extends RGBImageFilter { + private int percent; + + public BleachImageFilter(int percent) { + Assert.notFalse(percent >= 0 && percent <= 100); + this.percent = percent; + canFilterIndexColorModel = true; + } + public int percent() { return percent; } + public void percent(int percent) { percent = percent; } + + public int filterRGB(int x, int y, int rgb) { + DirectColorModel cm = + (DirectColorModel)ColorModel.getRGBdefault(); + + int alpha = cm.getAlpha(rgb); + int red = cm.getRed (rgb); + int green = cm.getGreen(rgb); + int blue = cm.getBlue (rgb); + double percentMultiplier = (double)percent/100; + + red = Math.min((int) + (red + (red * percentMultiplier)), 255); + green = Math.min((int) + (green + (green * percentMultiplier)), 255); + blue = Math.min((int) + (blue + (blue * percentMultiplier)), 255); + + alpha = alpha << 24; + red = red << 16; + green = green << 8; + + return alpha | red | green | blue; + } +} diff --git a/java/gjt/image/DissolveFilter.java b/java/gjt/image/DissolveFilter.java new file mode 100644 index 00000000000..027455b39b6 --- /dev/null +++ b/java/gjt/image/DissolveFilter.java @@ -0,0 +1,48 @@ +package gjt.image; + +import java.awt.image.*; +import gjt.Assert; + +/** + * A derivation of RGBImageFilter that partially or wholly + * dissolves an image.<p> + * + * Extent of dissolving is set by the setOpacity(int) method, + * which is passed an integer between 0 and 255 (inclusive). + * The integer represents the alpha value to be applied to + * every color in the image.<p> + * + * An alpha value of 255 signifies an opaque color, while an + * alpha value of 0 signifies a translucent color.<p> + * + * @version 1.0, Apr 1 1996 + * @author David Geary + * @see RGBImageFilter + */ +public class DissolveFilter extends RGBImageFilter { + private int opacity; + + public DissolveFilter() { + this(0); + } + public DissolveFilter(int opacity) { + canFilterIndexColorModel = true; + setOpacity(opacity); + } + public void setOpacity(int opacity) { + Assert.notFalse(opacity >= 0 && opacity <= 255); + this.opacity = opacity; + } + public int filterRGB(int x, int y, int rgb) { + DirectColorModel cm = + (DirectColorModel)ColorModel.getRGBdefault(); + int alpha = cm.getAlpha(rgb); + int red = cm.getRed (rgb); + int green = cm.getGreen(rgb); + int blue = cm.getBlue (rgb); + + alpha = opacity; + + return alpha << 24 | red << 16 | green << 8 | blue; + } +} diff --git a/java/gjt/image/ImageDissolver.java b/java/gjt/image/ImageDissolver.java new file mode 100644 index 00000000000..5d0e6a2daf6 --- /dev/null +++ b/java/gjt/image/ImageDissolver.java @@ -0,0 +1,132 @@ +package gjt.image; + +import java.awt.*; +import java.awt.image.*; +import gjt.Util; + +/** + * Given an image, an ImageDissolver produces an array of + * images of varying opacity that are used in the fadeIn() + * and fadeOut() methods for fading the image in and out + * respectively.<p> + * + * As a convenience, ImageDissolver has a static method: + * Image[] createImages() that creates the array of images + * mentioned above, in case clients would like to create their + * own array of images instead of using an ImageDissolver + * directly.<p> + * + * @version 1.0, Apr 1 1996 + * @author David Geary + * @see ThreeDBorder + * @see ImageButtonController + * @see SpringyImageButtonController + * @see StickyImageButtonController + * @see BleachImageFilter + * @see gjt.test.ImageButtonTest + */ +public class ImageDissolver { + private static int _defaultNumImages = 10, + _defaultPause = 50; + Component comp; + int numImages, pauseInterval; + Image image, offscreen; + Image[] dissolvedImages; + + static public Image[] createImages(Image image, + int numImages, + Component component) { + Image images[] = new Image[numImages]; + MediaTracker tracker = new MediaTracker(component); + + DissolveFilter filter; + FilteredImageSource fis; + + for(int i=0; i < numImages; ++i) { + filter = new DissolveFilter((255/(numImages-1))*i); + fis = new FilteredImageSource(image.getSource(), + filter); + + images[i] = component.createImage(fis); + tracker.addImage(images[i], i); + } + try { tracker.waitForAll(); } + catch(InterruptedException e) { } + + return images; + } + + public ImageDissolver(Component comp, Image image) { + this(comp, image, _defaultNumImages, _defaultPause); + } + public ImageDissolver(Component comp, Image im, + int numImages, int pause) { + this.image = im; + this.comp = comp; + this.numImages = numImages; + dissolvedImages = new Image[numImages]; + pauseInterval = pause; + + Util.waitForImage(comp, im); + dissolvedImages = createImages(image, numImages, comp); + } + public void fadeIn(int x, int y) { + if(offscreen == null) + offscreen = comp.createImage(image.getWidth(comp), + image.getHeight(comp)); + + Graphics offg = offscreen.getGraphics(); + Graphics compg = comp.getGraphics(); + + if(offg != null && compg != null) { + clearComponent(compg, x, y); + for(int i=0; i < numImages; ++i) { + blitImage(compg, offg, x, y, i); + pause (); + } + blitOpaqueImage(compg, offg, x, y); + } + } + public void fadeOut(int x, int y) { + if(offscreen == null) + offscreen = comp.createImage(image.getWidth(comp), + image.getHeight(comp)); + + Graphics offg = offscreen.getGraphics(); + Graphics compg = comp.getGraphics(); + + if(offg != null && compg != null) { + blitOpaqueImage(compg, offg, x, y); + for(int i=numImages-1; i >= 0; --i) { + clearOffscreen(); + blitImage (compg, offg, x, y, i); + pause (); + } + } + } + private void blitImage(Graphics compg, Graphics offg, + int x, int y, int index) { + offg.drawImage (dissolvedImages[index], 0, 0, comp); + compg.drawImage(offscreen, x, y, comp); + } + private void blitOpaqueImage(Graphics compg, Graphics offg, + int x, int y) { + offg.drawImage(image, 0, 0, comp); + compg.drawImage(offscreen, x, y, comp); + } + private void clearComponent(Graphics compg, int x, int y) { + clearOffscreen(); + compg.drawImage(offscreen, x, y, comp); + } + private void clearOffscreen() { + Graphics offg = offscreen.getGraphics(); + + offg.setColor(comp.getBackground()); + offg.fillRect(0, 0, + image.getWidth(comp), image.getHeight(comp)); + } + private void pause() { + try { Thread.currentThread().sleep(pauseInterval); } + catch(InterruptedException e) { } + } +} diff --git a/java/gjt/rubberband/Rubberband.java b/java/gjt/rubberband/Rubberband.java new file mode 100644 index 00000000000..be4b1b6ac05 --- /dev/null +++ b/java/gjt/rubberband/Rubberband.java @@ -0,0 +1,100 @@ +package gjt.rubberband; + +import java.awt.*; + +/** + * A abstract base class for rubberbands.<p> + * + * Rubberbands do their rubberbanding inside of a Component, + * which must be specified at construction time.<p> + * + * Subclasses are responsible for implementing + * <em>void drawLast(Graphics g)</em> and + * <em>void drawNext(Graphics g)</em>. + * + * drawLast() draws the appropriate geometric shape at the last + * rubberband location, while drawNext() draws the appropriate + * geometric shape at the next rubberband location. All of the + * underlying support for rubberbanding is taken care of here, + * including handling XOR mode setting; extensions of Rubberband + * need not concern themselves with anything but drawing the + * last and next geometric shapes.<p> + * + * @version 1.00, 12/27/95 + * @author David Geary + * @see RubberbandLine + * @see RubberbandRectangle + * @see RubberbandEllipse + * @see gjt.test.RubberbandTest + */ +abstract public class Rubberband { + protected Point anchor = new Point(0,0); + protected Point stretched = new Point(0,0); + protected Point last = new Point(0,0); + protected Point end = new Point(0,0); + + private Component component; + private boolean firstStretch = true; + + abstract public void drawLast(Graphics g); + abstract public void drawNext(Graphics g); + + public Rubberband(Component component) { + this.component = component; + } + public Point getAnchor () { return anchor; } + public Point getStretched() { return stretched; } + public Point getLast () { return last; } + public Point getEnd () { return end; } + + public void anchor(Point p) { + firstStretch = true; + anchor.x = p.x; + anchor.y = p.y; + + stretched.x = last.x = anchor.x; + stretched.y = last.y = anchor.y; + } + public void stretch(Point p) { + last.x = stretched.x; + last.y = stretched.y; + stretched.x = p.x; + stretched.y = p.y; + + Graphics g = component.getGraphics(); + if(g != null) { + g.setXORMode(component.getBackground()); + + if(firstStretch == true) firstStretch = false; + else drawLast(g); + + drawNext(g); + } + } + public void end(Point p) { + last.x = end.x = p.x; + last.y = end.y = p.y; + + Graphics g = component.getGraphics(); + if(g != null) { + g.setXORMode(component.getBackground()); + drawLast(g); + } + } + public Rectangle bounds() { + return new Rectangle(stretched.x < anchor.x ? + stretched.x : anchor.x, + stretched.y < anchor.y ? + stretched.y : anchor.y, + Math.abs(stretched.x - anchor.x), + Math.abs(stretched.y - anchor.y)); + } + + public Rectangle lastBounds() { + return new Rectangle( + last.x < anchor.x ? last.x : anchor.x, + last.y < anchor.y ? last.y : anchor.y, + Math.abs(last.x - anchor.x), + Math.abs(last.y - anchor.y)); + } +} diff --git a/java/gjt/rubberband/RubberbandEllipse.java b/java/gjt/rubberband/RubberbandEllipse.java new file mode 100644 index 00000000000..50ddb0cdd6b --- /dev/null +++ b/java/gjt/rubberband/RubberbandEllipse.java @@ -0,0 +1,32 @@ +package gjt.rubberband; + +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Rectangle; + +/** + * A Rubberband that does ellipses. + * + * @version 1.00, 12/27/95 + * @author David Geary + * @see Rubberband + * @see gjt.test.RubberbandTest + */ +public class RubberbandEllipse extends Rubberband { + private final int startAngle = 0; + private final int endAngle = 360; + + public RubberbandEllipse(Component component) { + super(component); + } + public void drawLast(Graphics graphics) { + Rectangle r = lastBounds(); + graphics.drawArc(r.x, r.y, + r.width, r.height, startAngle, endAngle); + } + public void drawNext(Graphics graphics) { + Rectangle r = bounds(); + graphics.drawArc(r.x, r.y, + r.width, r.height, startAngle, endAngle); + } +} diff --git a/java/gjt/rubberband/RubberbandLine.java b/java/gjt/rubberband/RubberbandLine.java new file mode 100644 index 00000000000..95daafa32a6 --- /dev/null +++ b/java/gjt/rubberband/RubberbandLine.java @@ -0,0 +1,25 @@ +package gjt.rubberband; + +import java.awt.Component; +import java.awt.Graphics; + +/** + * A Rubberband that does lines. + * + * @version 1.0, 12/27/95 + * @author David Geary + * @see Rubberband + * @see gjt.test.RubberbandTest + */ +public class RubberbandLine extends Rubberband { + public RubberbandLine(Component component) { + super(component); + } + public void drawLast(Graphics graphics) { + graphics.drawLine(anchor.x, anchor.y, last.x, last.y); + } + public void drawNext(Graphics graphics) { + graphics.drawLine(anchor.x, anchor.y, + stretched.x, stretched.y); + } +} diff --git a/java/gjt/rubberband/RubberbandPanel.java b/java/gjt/rubberband/RubberbandPanel.java new file mode 100644 index 00000000000..e4c25f4efb5 --- /dev/null +++ b/java/gjt/rubberband/RubberbandPanel.java @@ -0,0 +1,38 @@ +package gjt.rubberband; + +import java.awt.*; + +/** + * An extension of Panel which is fitted with a Rubberband. + * Handling of mouse events is automatically handled for + * rubberbanding.<p> + * + * Clients may set or get the Rubberband at any time.<p> + * + * @version 1.0, Dec 27 1995 + * @author David Geary + * @see Rubberband + * @see gjt.test.RubberbandTest + */ +public class RubberbandPanel extends Panel { + private Rubberband rubberband; + + public void setRubberband(Rubberband rubberband) { + this.rubberband = rubberband; + } + public Rubberband getRubberband() { + return rubberband; + } + public boolean mouseDown(Event event, int x, int y) { + rubberband.anchor(new Point(x,y)); + return false; + } + public boolean mouseDrag(Event event, int x, int y) { + rubberband.stretch(new Point(x,y)); + return false; + } + public boolean mouseUp(Event event, int x, int y) { + rubberband.end(new Point(x,y)); + return false; + } +} diff --git a/java/gjt/rubberband/RubberbandRectangle.java b/java/gjt/rubberband/RubberbandRectangle.java new file mode 100644 index 00000000000..bfcb1bfc32c --- /dev/null +++ b/java/gjt/rubberband/RubberbandRectangle.java @@ -0,0 +1,29 @@ +package gjt.rubberband; + +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Rectangle; + +/** + * A Rubberband that does rectangles. + * + * @version 1.00, 12/27/95 + * @author David Geary + * @see Rubberband + * @see gjt.test.RubberbandTest + */ +public class RubberbandRectangle extends Rubberband { + public RubberbandRectangle(Component component) { + super(component); + } + public void drawLast(Graphics graphics) { + Rectangle rect = lastBounds(); + graphics.drawRect(rect.x, rect.y, + rect.width, rect.height); + } + public void drawNext(Graphics graphics) { + Rectangle rect = bounds(); + graphics.drawRect(rect.x, rect.y, + rect.width, rect.height); + } +} diff --git a/java/gjt/test/AttributesPanel.java b/java/gjt/test/AttributesPanel.java new file mode 100644 index 00000000000..535a12edaeb --- /dev/null +++ b/java/gjt/test/AttributesPanel.java @@ -0,0 +1,78 @@ +package gjt.test; + +import java.applet.Applet; +import java.awt.*; +import gjt.*; + +class AttributesPanel extends Panel { + private Applet applet; + private Box iconbox, labelbox, checkboxbox; + private Panel panelInLabelbox = new Panel(); + private Panel panelInCheckboxbox = new Panel(); + private ExclusiveImageButtonPanel panelInIconbox; + + public AttributesPanel(Applet applet) { + GridBagLayout gbl = new GridBagLayout(); + GridBagConstraints gbc = new GridBagConstraints(); + + this.applet = applet; + panelInIconbox = new ExclusiveImageButtonPanel( + Orientation.HORIZONTAL); + + populateIconPanel (); + populateLabelPanel (); + populateCheckboxPanel(); + + iconbox = new Box(panelInIconbox, + "Meaningless Images"); + labelbox = new Box(panelInLabelbox, "Labels"); + checkboxbox = new Box(panelInCheckboxbox, "Fruits"); + iconbox.etchedOut(); + + setLayout(gbl); + gbc.anchor = GridBagConstraints.NORTH; + gbc.gridwidth = GridBagConstraints.REMAINDER; + gbc.weighty = 0.50; + gbl.setConstraints(iconbox, gbc); + add(iconbox); + gbl.setConstraints(labelbox, gbc); + add(labelbox); + + gbc.anchor = GridBagConstraints.SOUTH; + gbc.weighty = 0; + gbl.setConstraints(panelInCheckboxbox, gbc); + add(checkboxbox); + } + private void populateIconPanel() { + Image ballot, film, ticket; + + ballot = applet.getImage(applet.getCodeBase(), + "gifs/ballot_box.gif"); + ticket = applet.getImage(applet.getCodeBase(), + "gifs/movie_ticket.gif"); + film = applet.getImage(applet.getCodeBase(), + "gifs/filmstrip.gif"); + + panelInIconbox.add(ballot); + panelInIconbox.add(ticket); + panelInIconbox.add(film); + } + private void populateLabelPanel() { + panelInLabelbox.add(new Label("Label One")); + panelInLabelbox.add(new Label("Label Two")); + panelInLabelbox.add(new Label("Label Three")); + panelInLabelbox.add(new Label("Label Four")); + panelInLabelbox.add(new Label("Label Five")); + } + private void populateCheckboxPanel() { + CheckboxGroup group = new CheckboxGroup(); + + panelInCheckboxbox.setLayout(new GridLayout(3,0)); + panelInCheckboxbox.add(new Checkbox("apples", + group, false)); + panelInCheckboxbox.add(new Checkbox("oranges", + group, false)); + panelInCheckboxbox.add(new Checkbox("pears", + group, true)); + } +} diff --git a/java/gjt/test/BargaugeTest.java b/java/gjt/test/BargaugeTest.java new file mode 100644 index 00000000000..47733d6b0bf --- /dev/null +++ b/java/gjt/test/BargaugeTest.java @@ -0,0 +1,130 @@ +package gjt.test; + +import java.awt.*; +import java.applet.*; +import gjt.Bargauge; + +/** + * An array of either horizontal or vertical animated bargauges. + * The orientation of the bargauges is controlled by a parameter + * passed into the applet.<p> + * + * <em> + * Warning: An AWT bug causes this test to be a gluttenous + * consumer of resources (especially under Win95). A mouse down + * will halt the animation thread along with its consumption of + * resources.<p> + * </em> + * + * @version 1.0, April 25, 1996 + * @author David Geary + * @see gjt.test.UnitTest + * @see gjt.Bargauge + */ +public class BargaugeTest extends UnitTest { + private Bargauge[] gauges = new Bargauge[10]; + private Thread animatorThread; + private boolean running; + + public String title() { + return "Bargauge Test"; + } + public Panel centerPanel() { + return new BargaugeTestPanel( + gauges, getParameter("orientation")); + } + public boolean mouseDown(Event event, int x, int y) { + if(running == true) { + animatorThread.suspend(); + running = false; + } + else { + animatorThread.resume (); + running = true; + } + return true; + } + public void start() { + super.start(); + animatorThread = new BargaugeAnimator(gauges); + animatorThread.start(); + running = true; + } + public void stop() { + super.stop(); + animatorThread.suspend(); + running = false; + } +} + +class BargaugeTestPanel extends Panel { + public BargaugeTestPanel(Bargauge[] gauges, String orient) { + Panel bargaugePanel = new Panel(); + + setLayout(new BorderLayout()); + add("North", + new Label("Mouse Down Starts/Stops",Label.CENTER)); + add("Center", bargaugePanel); + + bargaugePanel.add(new BargaugeGridPanel(gauges,orient)); + } +} + +class BargaugeGridPanel extends Panel { + private Dimension preferredSize = new Dimension(200, 250); + + public BargaugeGridPanel(Bargauge[] gauges, String orient) { + Bargauge nextGauge; + Color color = Color.gray; + + if("horizontal".equals(orient)) + setLayout(new GridLayout(gauges.length,0,5,5)); + else + setLayout(new GridLayout(0,gauges.length,5,5)); + + for(int i=0; i < gauges.length; ++i) { + switch(i) { + case 1: color = Color.darkGray; break; + case 2: color = Color.blue; break; + case 3: color = Color.magenta; break; + case 4: color = Color.yellow; break; + case 5: color = Color.green; break; + case 6: color = Color.cyan; break; + case 7: color = Color.orange; break; + case 8: color = Color.pink; break; + case 9: color = Color.red; break; + case 10: color = Color.yellow; break; + } + nextGauge = new Bargauge(color); + gauges[i] = nextGauge; + add(nextGauge); + } + } + public Dimension preferredSize() { return preferredSize; } + public Dimension minimumSize () { return preferredSize; } +} + +class BargaugeAnimator extends Thread { + private Bargauge[] gauges; + private boolean firstAnimation = true; + + public BargaugeAnimator(Bargauge[] gauges) { + this.gauges = gauges; + } + public void run() { + int count = gauges.length; + + while(true) { + try { Thread.currentThread().sleep(500,0); } + catch(InterruptedException e) { } + for(int i=0; i < count; ++i) { + gauges[i].setFillPercent(Math.random() * 100); + gauges[i].fill(); + + if(firstAnimation) + System.out.println(gauges[i].toString()); + } + firstAnimation = false; + } + } +} diff --git a/java/gjt/test/BleachImageFilterTest.java b/java/gjt/test/BleachImageFilterTest.java new file mode 100644 index 00000000000..08fda725a08 --- /dev/null +++ b/java/gjt/test/BleachImageFilterTest.java @@ -0,0 +1,86 @@ +package gjt.test; + +import java.applet.Applet; +import java.awt.*; +import java.awt.image.FilteredImageSource; + +import gjt.Util; +import gjt.image.BleachImageFilter; + +/** + * Initially displays an unbleached image. Subsequent mouse + * clicks in the canvas containing the image toggle between + * a bleached version of the image and an unbleached version.<p> + * + * @version 1.0, Apr 1 1996 + * @author David Geary + * @see gjt.test.UnitTest + * @see gjt.image.BleachImageFilter + */ +public class BleachImageFilterTest extends UnitTest { + public String title() { + return "BleachImageFilter Test " + + "(Click below to Bleach/Unbleach Picture)"; + } + public Panel centerPanel() { + return new BleachImageFilterTestPanel(this); + } +} + +class BleachImageFilterTestPanel extends Panel { + BleachImageFilterTestCanvas canvas; + + public BleachImageFilterTestPanel(Applet applet) { + add(canvas = new BleachImageFilterTestCanvas(applet)); + } + public boolean mouseDown(Event event, int x, int y) { + canvas.toggleBleaching(); + canvas.repaint(); + return true; + } +} + +class BleachImageFilterTestCanvas extends Canvas { + private Image im; + private Image bleached; + private boolean showingBleached = false; + + public BleachImageFilterTestCanvas(Applet applet) { + int bp; + String bleachPercent = + applet.getParameter("bleachPercent"); + + if(bleachPercent != null) + bp = new Integer(bleachPercent).intValue(); + else + bp = 50; + + im = applet.getImage(applet.getCodeBase(), + "gifs/saint.gif"); + Util.waitForImage(this, im); + + FilteredImageSource source = + new FilteredImageSource(im.getSource(), + new BleachImageFilter(bp)); + + bleached = createImage(source); + Util.waitForImage(this, bleached); + + showImageSize(); + } + public Dimension preferredSize() { + return new Dimension(im.getWidth(this), + im.getHeight(this)); + } + public void paint(Graphics g) { + if(showingBleached) g.drawImage(bleached,0,0,this); + else g.drawImage(im, 0,0,this); + } + public void toggleBleaching() { + showingBleached = showingBleached ? false : true; + } + private void showImageSize() { + System.out.print ("Image width=" + im.getWidth(this)); + System.out.println(" height=" + im.getHeight(this)); + } +} diff --git a/java/gjt/test/BorderTest.java b/java/gjt/test/BorderTest.java new file mode 100644 index 00000000000..450b5ffc7ea --- /dev/null +++ b/java/gjt/test/BorderTest.java @@ -0,0 +1,202 @@ +package gjt.test; + +import java.applet.Applet; +import java.awt.*; +import gjt.Border; +import gjt.Box; +import gjt.EtchedBorder; +import gjt.ImageButton; +import gjt.ThreeDBorder; + +/** + * Creates 10 bordered Components: + * <dl> + * <dd> A Canvas (click in canvas to depress/raise the border). + * <dd> A Label with an etched out border. + * <dd> A TextField with an inset 3D border. + * <dd> A CheckBox with a default border. + * <dd> A List with a raised 3D border. + * <dd> A Choice with an etched in border. + * <dd> A Box with a raised 3D border. + * <dd> An ImageButton with a thick, red border. + * <dd> An AWT Button with a cyan border. + * <dd> A TextArea with a blue default-width border. + * </dl> + * + * @version 1.0, April 25, 1996 + * @author David Geary + * @see gjt.test.UnitTest + * @see gjt.Border + * @see gjt.ThreeDBorder + * @see gjt.EtchedBorder + */ +public class BorderTest extends UnitTest { + public String title() { + return "Border Test"; + } + public Panel centerPanel() { + return new BorderTestPanel(this); + } +} + +class BorderTestPanel extends Panel { + TextField tf = new TextField( + "Inset TextField: border 5 pixels, gap 5 pixels "); + ThreeDBorder threeDBorder; + EtchedBorder etchedLabel; + Border border; + + public BorderTestPanel(Applet applet) { + setLayout(new FlowLayout(FlowLayout.CENTER, 10, 10)); + + add(new BorderedCanvas()); + add(etchedLabel = + new EtchedBorder(new Label("Etched Label"))); + add(threeDBorder = new ThreeDBorder(tf, 5, 5)); + add(new Border(new Checkbox("Check Me Out"))); + add(makeThreeDBorderedList ()); + add(makeEtchedBorderedChoice ()); + add(makeThreeDBorderedCheckboxes()); + add(makeBorderedImageButton (applet)); + add(makeBorderedAWTButton ()); + add(makeBorderedTextArea ()); + + threeDBorder.inset(); + etchedLabel.etchedOut(); + } + private Border makeThreeDBorderedList() { + List list = new List(10, true); + + list.addItem("One"); + list.addItem("Two"); + list.addItem("Three"); + list.addItem("Four"); + list.addItem("Five"); + list.addItem("Six"); + list.addItem("Seven"); + list.addItem("Eight"); + list.addItem("Nine"); + list.addItem("Ten"); + list.addItem("Eleven"); + list.addItem("Twelve"); + list.addItem("Thirteen"); + list.addItem("Fourteen"); + list.addItem("Fiveteen"); + list.addItem("Sixteen"); + list.addItem("Seventeen"); + list.addItem("Eightteen"); + list.addItem("Nineteen"); + list.addItem("Twenty"); + + return new ThreeDBorder(list); + } + private Border makeEtchedBorderedChoice() { + Choice choice = new Choice(); + + choice.addItem("Toadies"); + choice.addItem("SilverChair"); + choice.addItem("Rug Burns"); + choice.addItem("Cracker"); + choice.addItem("Seven Mary Three"); + choice.addItem("Dishwalla"); + choice.addItem("Blues Traveler"); + choice.addItem("BottleRockets"); + choice.addItem("SpaceHog"); + + return new EtchedBorder(choice); + } + private Border makeBorderedImageButton(Applet applet) { + Image snail; + Border border; + + snail = applet.getImage(applet.getCodeBase(), + "gifs/snail.gif"); + border = new Border(new ImageButton(snail), 10); + border.setLineColor(Color.red); + + return border; + } + private Border makeBorderedAWTButton() { + Button button; + Border cyanBorder, blackBorder; + + button = new Button("Button Inside Two Borders"); + cyanBorder = new Border(button, 7); + cyanBorder.setLineColor(Color.cyan); + + blackBorder = new Border(cyanBorder); + + return blackBorder; + } + private Border makeThreeDBorderedCheckboxes() { + Panel panel = new Panel(); + Box box = new Box(panel, "Options"); + CheckboxGroup group = new CheckboxGroup(); + + panel.setLayout(new GridLayout(3,0)); + panel.add(new Checkbox("bordered", group, false)); + panel.add(new Checkbox("transparent", group, false)); + panel.add(new Checkbox("continuous", group, true)); + + return new ThreeDBorder(box, 4); + } + private Border makeBorderedTextArea() { + Border border; + + border = new Border( + new TextArea("Blue Bordered TextArea", 5, 30)); + border.setLineColor(Color.blue); + + return border; + } +} + +class BorderedCanvas extends ThreeDBorder { + public BorderedCanvas() { + super(new TestCanvas()); + } + public boolean mouseDown(Event event, int x, int y) { + if(isRaised()) paintInset (); + else paintRaised(); + return true; + } +} + +class TestCanvas extends Canvas { + private boolean centeredShowing = false; + private String centered = new String ("Red Centered Text"); + + public void paint(Graphics g) { + String canvas = "Canvas"; + String click = "Click Me"; + Dimension size = size(); + FontMetrics fm = g.getFontMetrics(); + + g.drawString(canvas, (size.width/2) - + (fm.stringWidth(canvas)/2), + fm.getHeight() - fm.getDescent()); + + g.drawString(click, (size.width/2) - + (fm.stringWidth(click)/2), + size.height - fm.getHeight() + + fm.getAscent()); + + if(centeredShowing == true) { + g.setColor(Color.red); + g.drawString(centered, + size.width/2-(fm.stringWidth(centered)/2), + size.height/2 - (fm.getHeight()/2) + + fm.getAscent()); + } + } + public Dimension preferredSize() { + FontMetrics fm = getGraphics().getFontMetrics(); + return new Dimension(fm.stringWidth(centered)+10, 100); + } + public boolean mouseUp(Event event, int x, int y) { + if(centeredShowing == false) centeredShowing = true; + else centeredShowing = false; + repaint(); + return true; + } +} diff --git a/java/gjt/test/BoxTest.java b/java/gjt/test/BoxTest.java new file mode 100644 index 00000000000..24e3de9213e --- /dev/null +++ b/java/gjt/test/BoxTest.java @@ -0,0 +1,100 @@ +package gjt.test; + +import java.applet.Applet; +import java.awt.*; +import gjt.Box; +import gjt.ExclusiveImageButtonPanel; +import gjt.Orientation; + +/** + * Three Boxes, each of which surrounds either: ImageButtons, + * Labels or Checkboxes. The Box surrounding the ImageButtons + * is etched out, while the other two Boxes are etched in.<p> + * + * @version 1.0, April 25, 1996 + * @author David Geary + * @see gjt.test.UnitTest + * @see gjt.ImageButton + * @see gjt.Box + */ +public class BoxTest extends UnitTest { + public String title() { + return "Box Test"; + } + public Panel centerPanel() { + return new BoxTestPanel(this); + } +} + +class BoxTestPanel extends Panel { + private Applet applet; + private Box iconbox, labelbox, checkboxbox; + private Panel panelInLabelbox = new Panel(); + private Panel panelInCheckboxbox = new Panel(); + private ExclusiveImageButtonPanel panelInIconbox; + + public BoxTestPanel(Applet applet) { + GridBagLayout gbl = new GridBagLayout(); + GridBagConstraints gbc = new GridBagConstraints(); + + this.applet = applet; + panelInIconbox = new ExclusiveImageButtonPanel( + Orientation.HORIZONTAL); + + populateIconPanel (); + populateLabelPanel (); + populateCheckboxPanel(); + + iconbox = new Box(panelInIconbox, + "Meaningless Images"); + labelbox = new Box(panelInLabelbox, "Labels"); + checkboxbox = new Box(panelInCheckboxbox, "Fruits"); + iconbox.etchedOut(); + + setLayout(gbl); + gbc.anchor = GridBagConstraints.NORTH; + gbc.gridwidth = GridBagConstraints.REMAINDER; + gbc.weighty = 0.50; + gbl.setConstraints(iconbox, gbc); + add(iconbox); + gbl.setConstraints(labelbox, gbc); + add(labelbox); + + gbc.anchor = GridBagConstraints.SOUTH; + gbc.weighty = 0; + gbl.setConstraints(checkboxbox, gbc); + add(checkboxbox); + } + private void populateIconPanel() { + Image ballot, film, ticket; + + ballot = applet.getImage(applet.getCodeBase(), + "gifs/ballot_box.gif"); + ticket = applet.getImage(applet.getCodeBase(), + "gifs/movie_ticket.gif"); + film = applet.getImage(applet.getCodeBase(), + "gifs/filmstrip.gif"); + + panelInIconbox.add(ballot); + panelInIconbox.add(ticket); + panelInIconbox.add(film); + } + private void populateLabelPanel() { + panelInLabelbox.add(new Label("Label One")); + panelInLabelbox.add(new Label("Label Two")); + panelInLabelbox.add(new Label("Label Three")); + panelInLabelbox.add(new Label("Label Four")); + panelInLabelbox.add(new Label("Label Five")); + } + private void populateCheckboxPanel() { + CheckboxGroup group = new CheckboxGroup(); + + panelInCheckboxbox.setLayout(new GridLayout(3,0)); + panelInCheckboxbox.add(new Checkbox("apples", + group, false)); + panelInCheckboxbox.add(new Checkbox("oranges", + group, false)); + panelInCheckboxbox.add(new Checkbox("pears", + group, true)); + } +} diff --git a/java/gjt/test/BumpAnimationTest.java b/java/gjt/test/BumpAnimationTest.java new file mode 100644 index 00000000000..81b6fb5ce8e --- /dev/null +++ b/java/gjt/test/BumpAnimationTest.java @@ -0,0 +1,107 @@ +package gjt.test; + +import java.net.URL; +import java.applet.Applet; +import java.awt.*; + +import gjt.Util; +import gjt.Orientation; +import gjt.animation.*; + +/** + * A simple animation playfield with one sprite that bounces + * off the boundaries of the playfield.<p> + * + * When the sprite bounces off the left wall, it plays a + * bump sequence once; when it bounces off the right wall + * it plays the bump sequence twice.<p> + * + * @version 1.0, Apr 1 1996 + * @author David Geary + * @see gjt.animation.Playfield + * @see gjt.animation.Sprite + */ +public class BumpAnimationTest extends UnitTest { + public String title() { + return "Bump Animation - Mouse Down Starts/Stops"; + } + public Panel centerPanel() { + return new BumpAnimationTestPanel(this); + } +} + +class BumpAnimationTestPanel extends Panel { + public BumpAnimationTestPanel(Applet applet) { + setLayout(new BorderLayout()); + add("Center", new BumpPlayfield(applet)); + } +} + +class BumpPlayfield extends Playfield { + private Applet applet; + private URL cb; + private Sprite javaDrinker; + private Sequence spinSequence, bumpSequence; + + public BumpPlayfield(Applet applet) { + this.applet = applet; + cb = applet.getCodeBase(); + makeSequencesAndSprites(); + } + public void paintBackground(Graphics g) { + Image bg = applet.getImage(cb, "gifs/background.gif"); + Util.wallPaper(this, g, bg); + } + public boolean mouseDown(Event event, int x, int y) { + if(running() == true) stop (); + else start(); + return true; + } + public void spriteCollision(Sprite sprite, Sprite sprite2) { + // Nothing to do: only 1 sprite! + } + public void edgeCollision(Sprite sprite, + Orientation orientation) { + if(orientation == Orientation.RIGHT || + orientation == Orientation.LEFT) { + if(sprite.getSequence() != bumpSequence) { + sprite.reverseX(); + + if(orientation == Orientation.RIGHT) + sprite.play(bumpSequence, 1); + else + sprite.play(bumpSequence, 2); + } + } + else + sprite.reverseY(); + } + private void makeSequencesAndSprites() { + String file; + Point startLoc = new Point(10, 10); + Image[] spinImages = new Image[19]; + Image[] bumpImages = new Image[6]; + + for(int i=0; i < spinImages.length; ++i) { + file = "gifs/spin"; + + if(i < 10) file += "0" + i + ".gif"; + else file += i + ".gif"; + + spinImages[i] = applet.getImage(cb, file); + } + for(int i=0; i < bumpImages.length; ++i) { + file = "gifs/bump0" + i + ".gif"; + bumpImages[i] = applet.getImage(cb, file); + } + spinSequence = new Sequence(this, spinImages); + bumpSequence = new Sequence(this, bumpImages); + javaDrinker = new Sprite(this, spinSequence, startLoc); + + spinSequence.setAdvanceInterval(100); + bumpSequence.setAdvanceInterval(200); + + javaDrinker.setMoveVector(new Point(2,2)); + addSprite(javaDrinker); + } +} diff --git a/java/gjt/test/ChoiceCardPanelTest.java b/java/gjt/test/ChoiceCardPanelTest.java new file mode 100644 index 00000000000..4ec27ac8945 --- /dev/null +++ b/java/gjt/test/ChoiceCardPanelTest.java @@ -0,0 +1,34 @@ +package gjt.test; + +import java.applet.Applet; +import java.awt.*; +import gjt.ChoiceCardPanel; + +/** + * A ChoiceCardPanel that controls three Panels.<p> + * + * @version 1.0, April 25, 1996 + * @author David Geary + * @see gjt.test.UnitTest + * @see gjt.ChoiceCardPanel + */ +public class ChoiceCardPanelTest extends UnitTest { + public String title() { return "Choice CardPanel Test"; } + public Panel centerPanel() { + return new ChoiceCardPanelTestPanel(this); + } +} + +class ChoiceCardPanelTestPanel extends Panel { + private ChoiceCardPanel mvp = new ChoiceCardPanel(); + + public ChoiceCardPanelTestPanel(Applet applet) { + setLayout(new BorderLayout()); + + mvp.addChoice("Attributes", + new AttributesPanel(applet)); + mvp.addChoice("Connections", new ConnectionsPanel()); + mvp.addChoice("Oracle", new OccupationOracle()); + add("Center", mvp); + } +} diff --git a/java/gjt/test/ColumnLayoutTest.java b/java/gjt/test/ColumnLayoutTest.java new file mode 100644 index 00000000000..fcef2151a25 --- /dev/null +++ b/java/gjt/test/ColumnLayoutTest.java @@ -0,0 +1,126 @@ +package gjt.test; + +import java.applet.Applet; +import java.net.URL; +import java.awt.*; +import gjt.*; + +/** + * Lays out 3 image buttons, and provides controls for setting + * orientations and gaps on the fly.<p> + * + * @version 1.0, April 25, 1996 + * @author David Geary + * @see gjt.test.UnitTest + * @see gjt.ImageButton + * @see gjt.Box + */ +public class ColumnLayoutTest extends UnitTest { + public String title() { + return "ColumnLayout Test"; + } + public Panel centerPanel() { + ColumnButtonPanel buttonPanel; + Panel panel = new Panel(); + + buttonPanel = new ColumnButtonPanel(this); + + panel.setLayout(new BorderLayout()); + panel.add("Center", buttonPanel); + panel.add("North", new Box(new ColumnPicker(buttonPanel), + "Column Layout Settings")); + return panel; + } +} + +class ColumnButtonPanel extends Panel implements DialogClient { + private ImageButton one, two, three; + private Panel panel = new Panel(); + private TenPixelBorder border = new TenPixelBorder(panel); + + public ColumnButtonPanel(Applet applet) { + URL cb = applet.getCodeBase(); + + one = new ImageButton(applet.getImage(cb, + "gifs/one.gif")); + two = new ImageButton(applet.getImage(cb, + "gifs/two.gif")); + three = new ImageButton(applet.getImage(cb, + "gifs/three.gif")); + + panel.setLayout(new ColumnLayout(0)); + panel.add(one); + panel.add(two); + panel.add(three); + + setLayout(new BorderLayout()); + add ("Center", border); + } + public void updateOrientations(Orientation horient, + Orientation vorient, + int gap) { + panel.setLayout(new ColumnLayout(horient, vorient, gap)); + border.validate(); + } + public void dialogDismissed(Dialog d) { } +} + +class ColumnPicker extends Panel { + private Label horientLabel = new Label("Horizontal:"); + private Label vorientLabel = new Label("Vertical:"); + private Label gapLabel = new Label("Gap:"); + + private Choice hchoice = new Choice(); + private Choice vchoice = new Choice(); + private Choice gapChoice = new Choice(); + + private ColumnButtonPanel buttonPanel; + + public ColumnPicker(ColumnButtonPanel buttonPanel) { + Panel orientations = new Panel(); + Panel gap = new Panel(); + + this.buttonPanel = buttonPanel; + hchoice.addItem("left"); + hchoice.addItem("center"); + hchoice.addItem("right"); + hchoice.select(1); + + vchoice.addItem("top"); + vchoice.addItem("center"); + vchoice.addItem("bottom"); + vchoice.select(1); + + gapChoice.addItem("0"); + gapChoice.addItem("5"); + gapChoice.addItem("10"); + gapChoice.addItem("15"); + gapChoice.addItem("20"); + + orientations.add(horientLabel); + orientations.add(hchoice); + orientations.add(vorientLabel); + orientations.add(vchoice); + + gap.add(gapLabel); + gap.add(gapChoice); + + add(new Box(orientations, "Orientations")); + add(new Box(gap, "Gap")); + } + public boolean action(Event event, Object what) { + String horient, vorient; + int gap; + + horient = hchoice.getSelectedItem(); + vorient = vchoice.getSelectedItem(); + gap = + (new Integer(gapChoice.getSelectedItem())).intValue(); + + buttonPanel.updateOrientations( + Orientation.fromString(horient), + Orientation.fromString(vorient), gap); + + return true; + } +} diff --git a/java/gjt/test/ComponentScrollerTest.java b/java/gjt/test/ComponentScrollerTest.java new file mode 100644 index 00000000000..4f0e4a2ec70 --- /dev/null +++ b/java/gjt/test/ComponentScrollerTest.java @@ -0,0 +1,205 @@ +package gjt.test; + +import java.awt.*; +import java.util.Vector; +import java.applet.Applet; +import java.net.URL; + +import gjt.Border; +import gjt.ButtonPanel; +import gjt.ColumnLayout; +import gjt.ComponentScroller; +import gjt.EtchedBorder; +import gjt.ImageButton; +import gjt.RowLayout; +import gjt.Separator; +import gjt.StickyImageButtonController; + +/** + * A phony image store, where you can purchase images.<p> + * + * @version 1.0, April 25, 1996 + * @author David Geary + * @see gjt.test.UnitTest + * @see Border + * @see ButtonPanel + * @see ImageButton + * @see Separator + * @see StickyImageButtonController + * @see ComponentScroller + */ +public class ComponentScrollerTest extends UnitTest { + public String title() { + return "ComponentScroller Test"; + } + public Panel centerPanel() { + return new ComponentScrollerTestPanel(this); + } +} + +class ComponentScrollerTestPanel extends Panel { + private ComponentScroller scroller; + private Panel purchasePanel; + private ImageButtonRow nextRow; + private String[][] imageNames = { + { "gifs/ballot_box.gif", "gifs/filmstrip.gif", + "gifs/fly.gif", "gifs/eagle.gif", + "gifs/bullet_hole.gif" }, + { "gifs/mad_hacker.gif", "gifs/tricycle.gif", + "gifs/light_bulb1.gif", "gifs/scissors.gif", + "gifs/palette.gif" }, + { "gifs/frog.gif", "gifs/gear.gif", + "gifs/wrench.gif", "gifs/www.gif", + "gifs/Dining.gif" }, + { "gifs/ant.gif", "gifs/abomb.gif", + "gifs/basketball.gif", "gifs/soccer.gif", + "gifs/skelly.gif" }, + }; + public ComponentScrollerTestPanel(Applet applet) { + URL base = applet.getCodeBase(); + Image nextImage; + Border border, blackBorder; + + purchasePanel = new Panel(); + purchasePanel.setLayout(new ColumnLayout()); + + for(int r=0; r < imageNames.length; ++r) { + nextRow = new ImageButtonRow(); + nextRow.setLayout(new RowLayout()); + + for(int c=0; c < imageNames[r].length; ++c) { + nextImage = applet.getImage(base, + imageNames[r][c]); + nextRow.add(nextImage); + } + purchasePanel.add(nextRow); + } + purchasePanel.add(new ButtonPurchaseForm()); + + scroller = new ComponentScroller(); + border = new Border(purchasePanel, 3, 2); + blackBorder = new Border(border, 1, 0); + + border.setLineColor(Color.gray); + blackBorder.setLineColor(Color.black); + scroller.setComponent(blackBorder); + + setLayout(new BorderLayout()); + add("Center", scroller); + } +} + +class ButtonPurchaseForm extends Panel { + TextField nameField = new TextField(25); + TextField addressField = new TextField(25); + TextField cityField = new TextField(15); + TextField stateField = new TextField(2); + + Choice paymentChoice = new Choice(); + + Button paymentButton = new Button("Purchase"); + Button cancelButton = new Button("Cancel"); + + public ButtonPurchaseForm() { + GridBagLayout gbl = new GridBagLayout(); + GridBagConstraints gbc = new GridBagConstraints(); + + Separator sep = new Separator(); + Label title = + new Label("Purchase A Fine Image Today"); + Label name = new Label("Name:"); + Label address = new Label("Address:"); + Label payment = new Label("Purchase Method:"); + Label phone = new Label("Phone:"); + Label city = new Label("City:"); + Label state = new Label("State:"); + + setLayout(gbl); + + paymentChoice.addItem("Visa"); + paymentChoice.addItem("MasterCard"); + paymentChoice.addItem("COD"); + + title.setFont(new Font("Times-Roman", + Font.BOLD + Font.ITALIC, + 16)); + gbc.anchor = GridBagConstraints.NORTH; + gbc.gridwidth = GridBagConstraints.REMAINDER; + gbl.setConstraints(title, gbc); + add(title); + + gbc.anchor = GridBagConstraints.NORTH; + gbc.gridwidth = GridBagConstraints.REMAINDER; + gbc.fill = GridBagConstraints.HORIZONTAL; + gbc.insets = new Insets(0,0,10,0); + gbl.setConstraints(sep, gbc); + add(sep); + + gbc.anchor = GridBagConstraints.WEST; + gbc.gridwidth = 1; + gbc.insets = new Insets(0,0,0,10); + gbl.setConstraints(name, gbc); + add(name); + + gbc.gridwidth = GridBagConstraints.REMAINDER; + gbl.setConstraints(nameField, gbc); + add(nameField); + + gbc.gridwidth = 1; + gbl.setConstraints(address, gbc); + add(address); + + gbc.gridwidth = GridBagConstraints.REMAINDER; + gbc.fill = GridBagConstraints.HORIZONTAL; + gbl.setConstraints(addressField, gbc); + add(addressField); + + gbc.gridwidth = 1; + gbl.setConstraints(city, gbc); + add(city); + + gbl.setConstraints(cityField, gbc); + add(cityField); + + gbl.setConstraints(state, gbc); + add(state); + + gbl.setConstraints(stateField, gbc); + gbc.gridwidth = GridBagConstraints.REMAINDER; + gbl.setConstraints(stateField, gbc); + add(stateField); + + gbc.gridwidth = 1; + gbl.setConstraints(payment, gbc); + gbc.insets = new Insets(5,0,5,0); + add(payment); + + gbc.gridwidth = GridBagConstraints.REMAINDER; + gbc.fill = GridBagConstraints.NONE; + gbl.setConstraints(paymentChoice, gbc); + add(paymentChoice); + + ButtonPanel buttonPanel = new ButtonPanel(); + + buttonPanel.add(paymentButton); + buttonPanel.add(cancelButton); + + gbc.anchor = GridBagConstraints.SOUTH; + gbc.insets = new Insets(5,0,0,0); + gbc.fill = GridBagConstraints.HORIZONTAL; + gbc.gridwidth = 4; + gbl.setConstraints(buttonPanel, gbc); + add(buttonPanel); + } +} +class ImageButtonRow extends Panel { + public ImageButtonRow() { + setLayout(new RowLayout()); + } + public void add(Image image) { + ImageButton button = new ImageButton(image); + add(button); + button.setController( + new StickyImageButtonController(button)); + } +} diff --git a/java/gjt/test/ConnectionsPanel.java b/java/gjt/test/ConnectionsPanel.java new file mode 100644 index 00000000000..7790d0709b1 --- /dev/null +++ b/java/gjt/test/ConnectionsPanel.java @@ -0,0 +1,9 @@ +package gjt.test; + +import java.awt.*; + +class ConnectionsPanel extends Panel { + public ConnectionsPanel() { + add(new Label("Connections")); + } +} diff --git a/java/gjt/test/DialogTest.java b/java/gjt/test/DialogTest.java new file mode 100644 index 00000000000..f92069b7c49 --- /dev/null +++ b/java/gjt/test/DialogTest.java @@ -0,0 +1,140 @@ +package gjt.test; + +import java.awt.*; +import java.applet.Applet; + +import gjt.Util; +import gjt.DialogClient; +import gjt.MessageDialog; +import gjt.ProgressDialog; +import gjt.QuestionDialog; +import gjt.YesNoDialog; + +/** + * Tests 4 gjt custom dialogs: + * <dl> + * <dd> MessageDialog (a dialog which displays a message) + * <dd> QuestionDialog (a dialog which asks a question) + * <dd> YesNoDialog (a dialog with yes/no buttons) + * <dd> ProgressDialog (a dialog which records progress of task) + * </dl> + * @version 1.0, April 25, 1996 + * @author David Geary + * @see gjt.test.UnitTest + * @see gjt.DialogClient + * @see gjt.MessageDialog + * @see gjt.ProgressDialog; + * @see gjt.QuestionDialog; + * @see gjt.YesNoDialog; + */ +public class DialogTest extends UnitTest { + public String title() { + return "Graphic Java Toolkit Dialog Test"; + } + public Panel centerPanel() { + return new DialogLauncher(); + } +} + +class DialogLauncher extends Panel implements DialogClient { + private MessageDialog messageDialog; + private QuestionDialog questionDialog; + private YesNoDialog yesNoDialog; + private ProgressDialog progressDialog; + + private Button messageDialogButton, questionDialogButton, + yesNoDialogButton, progressDialogButton; + + public DialogLauncher() { + setLayout(new GridLayout(0,1)); + + add(messageDialogButton = + new Button("Message Dialog")); + + add(questionDialogButton = + new Button("Question Dialog")); + + add(yesNoDialogButton = + new Button("YesNo Dialog")); + + add(progressDialogButton = + new Button("Progress Dialog")); + } + public boolean action(Event event, Object what) { + if(event.target == messageDialogButton) { + messageDialog = MessageDialog.getMessageDialog( + Util.getFrame(this), this, + "Example Message Dialog", + "This is an example of a message dialog."); + + messageDialog.show(); + } + else if(event.target == questionDialogButton) { + questionDialog = + new QuestionDialog(Util.getFrame(this), this, + "Example Question Dialog", + "Name: ", "Gumby", 45); + questionDialog.show(); + } + else if(event.target == yesNoDialogButton) { + yesNoDialog = + YesNoDialog.getYesNoDialog(Util.getFrame(this), + this, + "Example YesNo Dialog", + "Another cup of Java?"); + yesNoDialog.show(); + } + else if(event.target == progressDialogButton) { + progressDialog = + ProgressDialog.getProgressDialog( + Util.getFrame(this), + "Example Progress Dialog", + Color.blue); + + progressDialog.show(); + + ProgressThread thread = + new ProgressThread(progressDialog); + thread.start(); + } + + return true; + } + public void dialogDismissed(Dialog d) { + if(d == messageDialog) { + System.out.println("MessageDialog Down"); + } + if(d == questionDialog) { + if(questionDialog.wasCancelled()) + System.out.println("CANCELLED"); + else + System.out.println( + "Name: " + + questionDialog.getTextField().getText()); + } + if(d == yesNoDialog) { + if(yesNoDialog.answeredYes()) + System.out.println("YES"); + else + System.out.println("NO"); + } + } +} + +class ProgressThread extends Thread { + private ProgressDialog dialog; + private double percentComplete = 0; + + public ProgressThread(ProgressDialog dialog) { + this.dialog = dialog; + } + public void run() { + while(percentComplete <= 100) { + try { Thread.currentThread().sleep(500); } + catch(InterruptedException e) { } + + dialog.setPercentComplete(percentComplete); + percentComplete += 10; + } + } +} diff --git a/java/gjt/test/DrawnRectangleTest.java b/java/gjt/test/DrawnRectangleTest.java new file mode 100644 index 00000000000..19e3c195f7c --- /dev/null +++ b/java/gjt/test/DrawnRectangleTest.java @@ -0,0 +1,119 @@ +package gjt.test; + +import java.awt.*; +import gjt.DrawnRectangle; +import gjt.EtchedRectangle; +import gjt.ThreeDRectangle; + +/** + * 9 DrawnRectangles (some of which are EtchedRectangles + * and ThreeDRectangles) with varying characteristics such + * as line widths and colors.<p> + * + * A mouse down (any mouse button) in any of the rectangles + * causes information about the rectangle to be printed to + * System.out. (Output will go to Java Console in Netscape).<p> + * + * @version 1.0, April 25, 1996 + * @author David Geary + * @see gjt.test.UnitTest + * @see gjt.DrawnRectangle + * @see gjt.EtchedRectangle + * @see gjt.ThreeDRectangle + */ +public class DrawnRectangleTest extends UnitTest { + public String title() { + return "Drawn Rectangle Test"; + } + public Panel centerPanel() { + return new DrawnRectangleTestPanel(); + } +} + +class DrawnRectangleTestPanel extends Panel { + private DrawnRectangle drawnFilledOrange, + drawnFilledBlue, drawnBlue; + private EtchedRectangle etchedOut, + etchedIn, etchedFilledCyan; + private ThreeDRectangle thinRaised, + thinInset, thickRaised, thickInset; + + public DrawnRectangleTestPanel() { + drawnFilledOrange = + new DrawnRectangle (this, 10, 10, 100, 100); + drawnFilledBlue = + new DrawnRectangle (this, 135, 135, 100, 100); + drawnBlue = + new DrawnRectangle (this, 505, 135, 100, 100); + etchedFilledCyan = + new EtchedRectangle(this, 10, 135, 100, 100); + + etchedIn = new EtchedRectangle(this, 385, 10, 100, 100); + etchedOut= new EtchedRectangle(this, 505, 10, 100, 100); + + thinRaised = + new ThreeDRectangle(this, 135, 10, 100, 100); + thinInset = + new ThreeDRectangle(this, 260, 10, 100, 100); + thickRaised = + new ThreeDRectangle(this, 385, 135, 100, 100); + thickInset = + new ThreeDRectangle(this, 260, 135, 100, 100); + + drawnFilledOrange.setLineColor(Color.black); + + drawnFilledBlue.setLineColor(Color.yellow); + drawnFilledBlue.setThickness(3); + + drawnBlue.setLineColor(Color.blue); + drawnBlue.setThickness(5); + + thickRaised.setThickness(5); + thickInset.setThickness (5); + } + public Dimension preferredSize() { + return new Dimension(610, 270); + } + public void paint(Graphics g) { + drawnFilledOrange.paint(); + drawnFilledOrange.fill (Color.orange); + + drawnFilledBlue.paint (); + drawnFilledBlue.fill (Color.blue); + + drawnBlue.paint (); + + etchedIn.paintEtchedIn (); + etchedOut.paintEtchedOut(); + + etchedFilledCyan.paintEtchedIn(); + etchedFilledCyan.fill(Color.cyan); + + thinRaised.paintRaised (); + thinInset.paintInset (); + + thickRaised.paintRaised (); + + thickInset.paintInset (); + thickInset.fill (Color.red); + } + public boolean mouseDown(Event event, int x, int y) { + if(drawnFilledOrange.inside(x,y)) + show(drawnFilledOrange); + + if(drawnFilledBlue.inside(x,y)) show(drawnFilledBlue); + if(drawnBlue.inside(x,y)) show(drawnBlue); + if(etchedIn.inside(x,y)) show(etchedIn); + if(etchedOut.inside(x,y)) show(etchedOut); + if(etchedFilledCyan.inside(x,y)) show(etchedFilledCyan); + if(thinRaised.inside(x,y)) show(thinRaised); + if(thickRaised.inside(x,y)) show(thickRaised); + if(thinInset.inside(x,y)) show(thinInset); + if(thickInset.inside(x,y)) show(thickInset); + + return true; + } + private void show(DrawnRectangle drawnRectangle) { + System.out.println(drawnRectangle); + } +} diff --git a/java/gjt/test/FontDialogTest.java b/java/gjt/test/FontDialogTest.java new file mode 100644 index 00000000000..d0b535c27f9 --- /dev/null +++ b/java/gjt/test/FontDialogTest.java @@ -0,0 +1,95 @@ +package gjt.test; + +import java.awt.*; + +import gjt.FontDialog; +import gjt.DialogClient; +import gjt.Util; + +/** + * Activating the button causes the FontDialog to be displayed. + * Selecting a font from the FontDialog causes the button to + * use the selected font.<p> + * + * This unit test overrides FontDialog to reset the labels + * displayed in the buttons, and to reset the list of font + * sizes displayed. See FontDialog for a discussion of the + * overridden methods.<p> + * + *<em>Note: The FontDialog takes forever to come up in + * Netscape.</em> + * + * @version 1.0, Apr 25, 1996 + * @author David Geary + * @see gjt.test.UnitTest + * @see gjt.Util + * @see gjt.FontDialog + * @see gjt.DialogClient + */ +class LotsOfSizesFontDialog extends FontDialog { + private static String _defaultSizes[] = + { "8", "10", "12", "14", "16", + "18", "20", "22", "24", + "26", "28", "30", "32", "34", + "36", "38", "40", "42", "44", + "46", "48", "50", "52", "54", + "56", "58", "60", "62", "64", + "66", "68", "70", "72", "74", + "76", "78", "80", "82", "84", + "86", "88", "90", "92", "94", + "96", "98", "100" }; + + public LotsOfSizesFontDialog(Frame frame, + DialogClient client, + Font font) { + super(frame, client, font, true); + } + public String getPreviewButtonLabel() { + return "Preview Selected Font"; + } + public String getOkButtonLabel () { + return "I'll Take It"; + } + public String getCancelButtonLabel () { + return "Nevermind"; + } + public String[] getFontSizes () { + return _defaultSizes; + } +} + +public class FontDialogTest extends UnitTest { + public String title() { return "Font Dialog Test"; } + public Panel centerPanel() { + return new FontDialogTestPanel(); + } +} + +class FontDialogTestPanel extends Panel + implements DialogClient { + private Button fontButton; + + public FontDialogTestPanel() { + setLayout(new BorderLayout()); + add("Center", fontButton = new Button("Fonts ...")); + } + public boolean handleEvent(Event event) { + if(event.id == Event.ACTION_EVENT) { + LotsOfSizesFontDialog d; + d = new LotsOfSizesFontDialog(Util.getFrame(this), + this, + fontButton.getFont()); + d.show(); + } + return true; + } + public void dialogDismissed(Dialog d) { + FontDialog fontDialog = (FontDialog)d; + Font fontSelected = fontDialog.getFontSelected(); + + if(fontSelected != null) + fontButton.setFont(fontSelected); + + fontButton.requestFocus(); + } +} diff --git a/java/gjt/test/IconCardPanelTest.java b/java/gjt/test/IconCardPanelTest.java new file mode 100644 index 00000000000..33a65e1939c --- /dev/null +++ b/java/gjt/test/IconCardPanelTest.java @@ -0,0 +1,47 @@ +package gjt.test; + +import java.applet.Applet; +import java.awt.*; +import java.net.URL; +import gjt.IconCardPanel; + +/** + * A gjt.IconCardPanel that controls 3 Panels.<p> + * + * @version 1.0, April 25, 1996 + * @author David Geary + * @see gjt.test.UnitTest + * @see gjt.IconCardPanel + */ +public class IconCardPanelTest extends UnitTest { + public String title() { return "IconCardPanel Test"; } + public Panel centerPanel() { + return new CardPanelTestPanel(this); + } +} +class CardPanelTestPanel extends Panel { + IconCardPanel mvp = new IconCardPanel(); + + public CardPanelTestPanel(Applet applet) { + URL cb = applet.getCodeBase(); + + setLayout(new BorderLayout()); + + Image folks = applet.getImage(cb,"gifs/cell_phone.gif"); + Image pencil = applet.getImage(cb,"gifs/clipboard.gif"); + Image library = + applet.getImage(cb, "gifs/mad_hacker.gif"); + + mvp.addImageButton(folks, + "Attributes", + new AttributesPanel(applet)); + mvp.addImageButton(pencil, + "Connections", + new ConnectionsPanel()); + mvp.addImageButton(library, + "Oracle", + new OccupationOracle()); + + add("Center", mvp); + } +} diff --git a/java/gjt/test/ImageButtonTest.java b/java/gjt/test/ImageButtonTest.java new file mode 100644 index 00000000000..52df6efeba0 --- /dev/null +++ b/java/gjt/test/ImageButtonTest.java @@ -0,0 +1,130 @@ +package gjt.test; + +import java.applet.Applet; +import java.awt.*; +import gjt.Box; +import gjt.ImageButton; +import gjt.ImageButtonEvent; +import gjt.SpringyImageButtonController; +import gjt.StickyImageButtonController; + +/** + * 2 ImageButtons, one springy and the other sticky, both + * crabby.<p> + * + * Both ImageButtons come with an awt.Button that is used to + * enable/disable the ImageButton it's associated with.<p> + * + * ImageButtonEvents, along with mouse enter and mouse exit + * events for the two image buttons are printed out.<p> + * + * @version 1.0, Apr 25, 1996 + * @author David Geary + * @see gjt.test.UnitTest + * @see gjt.ImageButton + * @see gjt.ImageButtonEvent + * @see gjt.SpringyImageButtonController + * @see gjt.StickyImageButtonController + */ +public class ImageButtonTest extends UnitTest { + public String title() { + return "ImageButton Test"; + } + public Panel centerPanel() { + return new ImageButtonTestPanel(this); + } +} + +class ImageButtonTestPanel extends Panel { + private ImageButton springyButton; + private Button springyButtonEnabler; + private ImageButton stickyButton; + private Button stickyButtonEnabler; + + public ImageButtonTestPanel(Applet applet) { + Image image; + Box springyBox, stickyBox; + GridBagLayout gbl = new GridBagLayout(); + GridBagConstraints gbc = new GridBagConstraints(); + + image = + applet.getImage(applet.getCodeBase(), "gifs/crab.gif"); + + springyButton = new ImageButton(image); + springyButtonEnabler = new Button ("Disable"); + stickyButton = new ImageButton(image); + stickyButtonEnabler = new Button ("Disable"); + + stickyButton.setController( + new StickyImageButtonController(stickyButton)); + + setLayout(gbl); + + gbc.anchor = GridBagConstraints.NORTH; + springyBox = new Box(springyButton, "Springy"); + gbc.insets = new Insets(10,0,0,0); + gbl.setConstraints(springyBox, gbc); add(springyBox); + + gbc.gridwidth = GridBagConstraints.REMAINDER; + gbc.insets = new Insets(45,10,0,0); + gbl.setConstraints(springyButtonEnabler, gbc); + add(springyButtonEnabler); + + gbc.anchor = GridBagConstraints.NORTH; + gbc.gridwidth = 1; + stickyBox = new Box(stickyButton, "Sticky"); + gbc.insets = new Insets(10,0,0,0); + gbc.weighty = 1.0; + gbl.setConstraints(stickyBox, gbc); add(stickyBox); + + gbc.gridwidth = GridBagConstraints.REMAINDER; + gbc.insets = new Insets(45,10,0,0); + gbl.setConstraints(stickyButtonEnabler, gbc); + add(stickyButtonEnabler); + } + public boolean action(Event event, Object what) { + Button button = (Button)event.target; + String label = (String)what; + + if(button == stickyButtonEnabler) { + if(label.equals("Disable")) stickyButton.disable(); + else stickyButton.enable(); + } + else { + if(label.equals("Disable")) springyButton.disable(); + else springyButton.enable(); + } + if(label.equals("Disable")) button.setLabel("Enable"); + else button.setLabel("Disable"); + + return true; + } + public boolean handleEvent(Event event) { + boolean eventHandled = false; + + if(event instanceof ImageButtonEvent) { + System.out.println("ImageButton " + event); + eventHandled = true; + } + if(event.id == Event.MOUSE_ENTER) { + if(event.target == stickyButton) + System.out.println("Sticky Button Entered"); + + else if(event.target == springyButton) + System.out.println("Springy Button Entered"); + + eventHandled = true; + } + if(event.id == Event.MOUSE_EXIT) { + if(event.target == stickyButton) + System.out.println("Sticky Button Exited"); + + else if(event.target == springyButton) + System.out.println("Springy Button Exited"); + + eventHandled = true; + } + if(eventHandled) return true; + else return super.handleEvent(event); + } +} diff --git a/java/gjt/test/ImageDissolverTest.java b/java/gjt/test/ImageDissolverTest.java new file mode 100644 index 00000000000..c157408d2af --- /dev/null +++ b/java/gjt/test/ImageDissolverTest.java @@ -0,0 +1,69 @@ +package gjt.test; + +import java.applet.Applet; +import java.awt.*; +import java.awt.image.FilteredImageSource; + +import gjt.Util; +import gjt.image.ImageDissolver; + +/** + * Initially displays an image. Subsequent mouse clicks in the + * canvas containing the image cause the image to fade in or + * fade out, depending upon it's current state.<p> + * + * @version 1.0, Apr 1 1996 + * @author David Geary + * @see gjt.test.UnitTest + * @see gjt.image.DissolveFilter + * @see gjt.image.ImageDissolver + */ +public class ImageDissolverTest extends UnitTest { + public String title() { + return "ImageDissolver Test " + + "(Click Below to Fade Picture In/Out)"; + } + public Panel centerPanel() { + return new ImageDissolverTestPanel(this); + } +} + +class ImageDissolverTestPanel extends Panel { + ImageDissolverTestCanvas canvas; + + public ImageDissolverTestPanel(Applet applet) { + add(canvas = new ImageDissolverTestCanvas(applet)); + } + public boolean mouseDown(Event event, int x, int y) { + canvas.doFade(); + return true; + } +} + +class ImageDissolverTestCanvas extends Canvas { + private boolean isFaded = false; + private Image image; + private ImageDissolver dissolver; + + public ImageDissolverTestCanvas(Applet applet) { + image = + applet.getImage(applet.getCodeBase(),"gifs/saint.gif"); + + Util.waitForImage(this, image); + dissolver = new ImageDissolver(this, image); + } + public void paint(Graphics g) { + if( ! isFaded) + g.drawImage(image, 0, 0, this); + } + public Dimension preferredSize() { + return new Dimension(image.getWidth(this), + image.getHeight(this)); + } + public void doFade() { + if(isFaded) dissolver.fadeIn (0,0); + else dissolver.fadeOut(0,0); + + isFaded = isFaded ? false : true; + } +} diff --git a/java/gjt/test/ImageScrollerTest.java b/java/gjt/test/ImageScrollerTest.java new file mode 100644 index 00000000000..0476682eb6d --- /dev/null +++ b/java/gjt/test/ImageScrollerTest.java @@ -0,0 +1,55 @@ +package gjt.test; + +import java.awt.*; +import java.applet.Applet; +import java.net.URL; + +import gjt.ImageScroller; +import gjt.Util; + +/** + * Four images are loaded; subsequent mouse clicks cycle + * through the images, that are displayed in an ImageScroller. + * + * @version 1.0, April 25, 1996 + * @author David Geary + * @see gjt.test.UnitTest + * @see gjt.Scroller + * @see gjt.ImageScroller + */ +public class ImageScrollerTest extends UnitTest { + public String title() { + return "ImageScroller Test"; + } + public Panel centerPanel() { + return new ImageScrollerTestPanel(this); + } +} + +class ImageScrollerTestPanel extends Panel { + private Image[] images = new Image[4]; + private int imageIndex = 0; + private ImageScroller scroller; + + public ImageScrollerTestPanel(Applet applet) { + URL cb = applet.getCodeBase(); + + images[0]=applet.getImage(cb,"gifs/ashleyAndRoy.gif"); + images[1]=applet.getImage(cb,"gifs/ashleyAndSabre.gif"); + images[2]=applet.getImage(cb,"gifs/anjinAndMariko.gif"); + images[3]=applet.getImage(cb,"gifs/ashleyAndAnjin.gif"); + + setLayout(new BorderLayout()); + add("Center", scroller = new ImageScroller(images[0])); + } + public boolean mouseUp(Event event, int x, int y) { + if(imageIndex == images.length-1) imageIndex = 0; + else imageIndex++; + + Util.setCursor(Frame.WAIT_CURSOR, this); + scroller.resetImage(images[imageIndex]); + Util.setCursor(Frame.DEFAULT_CURSOR, this); + + return true; + } +} diff --git a/java/gjt/test/LabelCanvasTest.java b/java/gjt/test/LabelCanvasTest.java new file mode 100644 index 00000000000..cb4c0a857ae --- /dev/null +++ b/java/gjt/test/LabelCanvasTest.java @@ -0,0 +1,75 @@ +package gjt.test; +import java.applet.Applet; +import java.awt.Event; +import java.awt.Panel; +import java.awt.Insets; +import java.awt.Graphics; +import gjt.LabelCanvas; +import gjt.SelectionEvent; +import gjt.Util; + +/** + * Four LabelCanvases, each with different insets. The leftmost + * LabelCanvas has standard insets (2 all around), while the + * other three were constructed as follows: + * <pre> + * insetFive.setInsets (new Insets(5,5,5,5)); + * insetTen.setInsets (new Insets(10,10,10,10)); + * insetFifteen.setInsets(new Insets(15,15,15,15)); + * </pre><p> + * + * LabelCanvases generate SelectionEvents, that we watch + * for in our handleEvent() method, and print out.<p> + * + * @version 1.0, April 25, 1996 + * @author David Geary + * @see gjt.test.UnitTest + * @see gjt.LabelCanvas + */ +public class LabelCanvasTest extends UnitTest { + public String title() { return "LabelCanvas Test"; } + public Panel centerPanel() { + return new LabelCanvasTestPanel(this); + } +} + +class LabelCanvasTestPanel extends Panel { + Applet applet; + public LabelCanvasTestPanel(Applet applet) { + this.applet = applet; + LabelCanvas standard = + new LabelCanvas("Standard Insets"); + LabelCanvas insetFive = + new LabelCanvas("Insets = Five"); + LabelCanvas insetTen = + new LabelCanvas("Insets = Ten"); + LabelCanvas insetFifteen = + new LabelCanvas("Insets = Fifteen"); + + insetFive.setInsets (new Insets(5,5,5,5)); + insetTen.setInsets (new Insets(10,10,10,10)); + insetFifteen.setInsets(new Insets(15,15,15,15)); + + add(standard); + add(insetFive); + add(insetTen); + add(insetFifteen); + } + public boolean handleEvent(Event event) { + if(event instanceof SelectionEvent) { + SelectionEvent sevent = (SelectionEvent)event; + LabelCanvas canvas = (LabelCanvas)event.target; + + if(sevent.isSelected()) + System.out.println("LabelCanvas " + + canvas.getLabel() + + " selected"); + else + System.out.println("LabelCanvas " + + canvas.getLabel() + + " deselected"); + return true; + } + return super.handleEvent(event); + } +} diff --git a/java/gjt/test/MessageDialogTest.java b/java/gjt/test/MessageDialogTest.java new file mode 100644 index 00000000000..6efddd08cb4 --- /dev/null +++ b/java/gjt/test/MessageDialogTest.java @@ -0,0 +1,50 @@ + +package gjt.test; + +import java.awt.*; +import java.applet.Applet; + +import gjt.MessageDialog; +import gjt.DialogClient; +import gjt.Util; + +/** + * Simple unit test that exercises gjt.MessageDialog. This + * unit test serves to illustrate the use of gjt.DialogClient. + * For a unit test which covers all of the gjt dialogs, + * see gjt.test.DialogTest. + * + * @version 1.0, April 25, 1996 + * @author David Geary + * @see gjt.test.UnitTest + * @see gjt.DialogClient + * @see gjt.MessageDialog + */ +public class MessageDialogTest extends UnitTest { + public String title() { + return "Message Dialog Test"; + } + public Panel centerPanel() { + return new MessageDialogLauncher(); + } +} + +class MessageDialogLauncher extends Panel + implements DialogClient { + private MessageDialog messageDialog; + + public MessageDialogLauncher() { + add(new Button("Show Message Dialog")); + } + public boolean action(Event event, Object what) { + messageDialog = MessageDialog.getMessageDialog( + Util.getFrame(this), this, + "Example Message Dialog", + "This is an example of a message dialog."); + messageDialog.show(); + return true; + } + public void dialogDismissed(Dialog d) { + System.out.println("MessageDialog Down"); + } +} diff --git a/java/gjt/test/OccupationOracle.java b/java/gjt/test/OccupationOracle.java new file mode 100644 index 00000000000..a34c2ad2064 --- /dev/null +++ b/java/gjt/test/OccupationOracle.java @@ -0,0 +1,334 @@ +package gjt.test; + +import java.applet.Applet; +import java.awt.*; + +// The OccupationOracle class makes a guess at a person's occupation +// within an engineering organization based on a few "key" traits. +// Invalid entries in numeric fields result in an "Unknown" occupation. +// This applet uses the awt.GridBagLayout class to structure the +// occupation form. The awt.GridBagLayout class allows fields to +// be placed in rows and columns within a form. Each component +// is given a "display area" based on the constraints in effect +// when it is added to the layout. + +// Author: Jerry Jackson (thanks, sifu) + +public class OccupationOracle extends Panel { + + // Construct the form. Create each component of the form and + // add it to the layout. Initialize the occupation to "Unknown". + + public OccupationOracle() { + + // Use the GridBagLayout layout to construct rows and + // columns. + + GridBagLayout gridbag = new GridBagLayout(); + + // Create a new set of constraints to use when adding + // a component to the layout. The constraint values + // in effect when a component is added to the layout + // are cloned and stored in conjunction with the component + // by the layout. + + GridBagConstraints constraints = new GridBagConstraints(); + + // Set the font for the form. + + //setFont(new Font("TimesRoman", Font.BOLD, 12)); + + // Associate the GridBagLayout object with the applet. + + setLayout(gridbag); + + // The "anchor" constraint determines how a component + // is justified within its display area. + + constraints.anchor = GridBagConstraints.WEST; + + // Determines how much space should be given to this component. + // if left at 0.0, all components clump up in the middle as the + // padding is applied to the outside. + + constraints.weightx = 1.0; + + // Create a name label and text field. + + makeNameField(); + + // Setting the "gridwidth" constraint to 1 will + // cause the component to take up the minimum + // horizontal space in its row. + + constraints.gridwidth = 1; + + // "addFormComponent" will associate the current constraints + // with a component and add the component to the form. + + addFormComponent(gridbag, nameLabel, constraints); + + // Setting the "gridwidth" constraint to REMAINDER will + // cause the component to fill up the remainder of its row. + // i.e. it will be the last entry in the row. + + constraints.gridwidth = GridBagConstraints.REMAINDER; + + // The "fill" constraint tells what to do if the item is in + // a area larger than it is. In this case we want to fill + // any extra horizontal space. + + constraints.fill = GridBagConstraints.HORIZONTAL; + + addFormComponent(gridbag, nameField, constraints); + + // Create and add an age label and text field. + + makeAgeField(); + + constraints.gridwidth = 1; + constraints.fill = GridBagConstraints.NONE; + constraints.weightx = 0.0; + addFormComponent(gridbag, ageLabel, constraints); + constraints.gridwidth = GridBagConstraints.REMAINDER; + constraints.weightx = 1.0; + addFormComponent(gridbag, ageField, constraints); + + // Create and add a world view label and a single checkbox + // for a true/false value. + + makeWorldViewField(); + + constraints.gridwidth = 1; + constraints.weightx = 0.0; + addFormComponent(gridbag, worldViewLabel, constraints); + constraints.gridwidth = GridBagConstraints.REMAINDER; + constraints.weightx = 1.0; + addFormComponent(gridbag, worldViewField, constraints); + + + // Create and add a coffee consumption label and text field. + + makeCoffeeField(); + + constraints.gridwidth = 1; + constraints.weightx = 0.0; + addFormComponent(gridbag, coffeeLabel, constraints); + constraints.gridwidth = GridBagConstraints.REMAINDER; + constraints.weightx = 1.0; + addFormComponent(gridbag, coffeeField, constraints); + + + // Create and add a fashion sense label and a checkbox + // group that has three mutually exclusive values. + + makeFashionField(); + + constraints.gridwidth = GridBagConstraints.REMAINDER; + constraints.weightx = 0.0; + constraints.weighty = 0.0; + addFormComponent(gridbag, fashionLabel, constraints); + + // The three checkboxes that represent fashion sense. + + addFormComponent(gridbag, low, constraints); + addFormComponent(gridbag, medium, constraints); + addFormComponent(gridbag, high, constraints); + + // The Occupation field is output only. + + makeOccupationField(); + + constraints.gridwidth = 1; + constraints.weightx = 0.0; + constraints.weighty = 1.0; + constraints.fill = GridBagConstraints.NONE; + addFormComponent(gridbag, occupationLabel, constraints); + constraints.fill = GridBagConstraints.HORIZONTAL; + constraints.gridwidth = GridBagConstraints.REMAINDER; + constraints.weightx = 1.0; + addFormComponent(gridbag, occupationField, constraints); + + // Display the initial "Unknown" occupation. + + recalculateOccupation(); + + resize(400, 250); + } + + // The paint() method for this applet just calls the paintComponents() + // method which is defined by the Container class. It causes all + // the components visible within the Container to get painted. + + public void paint(Graphics g) { + paintComponents(g); + } + + // When any action occurs within the form we do the same thing: + // recalculate the person's occupation. + + public boolean action(Event event, Object arg) { + recalculateOccupation(); + return true; + } + + // A helper function that associates constraints with a component + // and adds it to the form. + + private void addFormComponent(GridBagLayout grid, Component comp, + GridBagConstraints c) { + grid.setConstraints(comp, c); + add(comp); + } + + + // recalculateOccupation() fetches the values of each component + // and computes an occupation based on some truly stupid heuristics. + + private void recalculateOccupation() { + + // If we don't have a name yet we might incorrectly categorize + // the CEO! + + if (nameField.getText() == "") { + occupationField.setText("Unknown"); + } + + // Fetch other important values that we'll use in our + // calculations. + + int age; + int coffeeConsumption; + boolean binaryView = worldViewField.getState(); + + + // Try to fetch integer values for age and coffeeConsumption. + // If the values in the fields can't be parsed as integers, + // set the occupation to "Unknown". + + try { + age = Integer.parseInt(ageField.getText()); + coffeeConsumption = Integer.parseInt(coffeeField.getText()); + } catch (Exception e) { + occupationField.setText("Unknown"); + return; + } + + // Check for the CEO. + + String name = nameField.getText(); + + if (name.endsWith("II") || + name.endsWith("III") || + name.endsWith("IV")) { + + if (age < 35 || coffeeConsumption < 4) { + occupationField.setText("Junior Executive"); + } else { + occupationField.setText("CEO"); + } + + return; + } + + // Fashion sense is a critical piece of information. + // The getCurrent() method of CheckboxGroup returns whichever + // Checkbox in the group is currently selected. Only one + // can be selected at a time. + + Checkbox fashionValue = fashionGroup.getCurrent(); + + if (fashionValue == low || fashionValue == medium) { + + // There are two kinds of people in the world: those who + // divide people into two kinds and those who don't. + + if (binaryView && coffeeConsumption >= 4) { + occupationField.setText("Engineer"); + + } else if ((age > 40 && binaryView) || + (age < 40 && coffeeConsumption >= 4)) { + occupationField.setText("Engineering Manager"); + + } else { + occupationField.setText("Product Manager"); + } + + } else { + + // High fashion sense. Not an engineer! + + if (binaryView || coffeeConsumption >= 4) { + occupationField.setText("Vice President"); + + } else { + occupationField.setText("Product Marketing"); + } + } + } + + // Helper functions to create form components. + + private void makeNameField() { + nameLabel = new Label("Name: "); + nameField = new TextField(40); + } + + private void makeAgeField() { + ageLabel = new Label("Age: "); + ageField = new TextField(3); + } + + private void makeOccupationField() { + occupationLabel = new Label("Occupation: "); + occupationField = new TextField(40); + } + + private void makeWorldViewField() { + worldViewLabel = new Label("Binary World View: "); + worldViewField = new Checkbox(); + } + + private void makeCoffeeField() { + coffeeLabel = new Label("Coffee consumption: "); + coffeeField = new TextField(3); + } + + private void makeFashionField() { + fashionLabel = new Label("Fashion sense:"); + + fashionGroup = new CheckboxGroup(); + low = new Checkbox("Low ", fashionGroup, false); + medium = new Checkbox("Medium", fashionGroup, true); + high = new Checkbox("High ", fashionGroup, false); + } + + // Text fields. + + private TextField nameField; + private TextField ageField; + private TextField coffeeField; + private TextField occupationField; + + // Labels. + + private Label nameLabel; + private Label ageLabel; + private Label coffeeLabel; + private Label fashionLabel; + private Label worldViewLabel; + private Label occupationLabel; + + // Checkboxes. + + private Checkbox worldViewField; + private Checkbox low; + private Checkbox medium; + private Checkbox high; + + // The fashion sense checkbox group. + + private CheckboxGroup fashionGroup; +} + + diff --git a/java/gjt/test/RowLayoutTest.java b/java/gjt/test/RowLayoutTest.java new file mode 100644 index 00000000000..eb7b419ca17 --- /dev/null +++ b/java/gjt/test/RowLayoutTest.java @@ -0,0 +1,124 @@ +package gjt.test; + +import java.applet.Applet; +import java.net.URL; +import java.awt.*; +import gjt.*; + +/** + * Lays out 3 image buttons, and provides controls for setting + * orientations and gaps on the fly.<p> + * + * @version 1.0, April 25, 1996 + * @author David Geary + * @see gjt.test.UnitTest + * @see gjt.ImageButton + * @see gjt.Box + */ +public class RowLayoutTest extends UnitTest { + public String title() { + return "RowLayout Test"; + } + public Panel centerPanel() { + RowButtonPanel buttonPanel = new RowButtonPanel(this); + Panel panel = new Panel(); + + panel.setLayout(new BorderLayout()); + panel.add("Center", buttonPanel); + panel.add("North", new Box(new RowPicker(buttonPanel), + "Row Layout Settings")); + return panel; + } +} + +class RowButtonPanel extends Panel implements DialogClient { + private ImageButton one, two, three; + private Panel panel = new Panel(); + private TenPixelBorder border = new TenPixelBorder(panel); + + public RowButtonPanel(Applet applet) { + URL cb = applet.getCodeBase(); + + one = new ImageButton(applet.getImage(cb, + "gifs/one.gif")); + two = new ImageButton(applet.getImage(cb, + "gifs/two.gif")); + three = new ImageButton(applet.getImage(cb, + "gifs/three.gif")); + + panel.setLayout(new RowLayout(0)); + panel.add(one); + panel.add(two); + panel.add(three); + + setLayout(new BorderLayout()); + add ("Center", border); + } + public void updateOrientations(Orientation horient, + Orientation vorient, + int gap) { + panel.setLayout(new RowLayout(horient, vorient, gap)); + border.validate(); + } + public void dialogDismissed(Dialog d) { } +} + +class RowPicker extends Panel { + private Label horientLabel = new Label("Horizontal:"); + private Label vorientLabel = new Label("Vertical:"); + private Label gapLabel = new Label("Gap:"); + + private Choice hchoice = new Choice(); + private Choice vchoice = new Choice(); + private Choice gapChoice = new Choice(); + + private RowButtonPanel buttonPanel; + + public RowPicker(RowButtonPanel buttonPanel) { + Panel orientations = new Panel(); + Panel gap = new Panel(); + + this.buttonPanel = buttonPanel; + hchoice.addItem("left"); + hchoice.addItem("center"); + hchoice.addItem("right"); + hchoice.select(1); + + vchoice.addItem("top"); + vchoice.addItem("center"); + vchoice.addItem("bottom"); + vchoice.select(1); + + gapChoice.addItem("0"); + gapChoice.addItem("5"); + gapChoice.addItem("10"); + gapChoice.addItem("15"); + gapChoice.addItem("20"); + + orientations.add(horientLabel); + orientations.add(hchoice); + orientations.add(vorientLabel); + orientations.add(vchoice); + + gap.add(gapLabel); + gap.add(gapChoice); + + add(new Box(orientations, "Orientations")); + add(new Box(gap, "Gap")); + } + public boolean action(Event event, Object what) { + String horient, vorient; + int gap; + + horient = hchoice.getSelectedItem(); + vorient = vchoice.getSelectedItem(); + gap = + (new Integer(gapChoice.getSelectedItem())).intValue(); + + buttonPanel.updateOrientations( + Orientation.fromString(horient), + Orientation.fromString(vorient), gap); + + return true; + } +} diff --git a/java/gjt/test/RubberbandTest.java b/java/gjt/test/RubberbandTest.java new file mode 100644 index 00000000000..ae256fb2c3a --- /dev/null +++ b/java/gjt/test/RubberbandTest.java @@ -0,0 +1,112 @@ +package gjt.test; + +import java.awt.*; +import gjt.DrawingPanel; +import gjt.Separator; +import gjt.RowLayout; +import gjt.rubberband.*; + +/** + * A simple drawing applet that demonstrates the utility of + * the gjt.rubberband package.<p> + * + * Note that this unit test also serves as the unit test for + * gjt.DrawingPanel.<p> + * + * @version 1.0, April 25, 1996 + * @author David Geary + * @see gjt.test.UnitTest + * @see gjt.DrawingPanel + * @see gjt.rubberband.Rubberband + * @see gjt.rubberband.RubberbandLine + * @see gjt.rubberband.RubberbandRectangle + * @see gjt.rubberband.RubberbandEllipse + * @see gjt.rubberband.RubberbandPanel + */ +public class RubberbandTest extends UnitTest { + public String title() { + return "Rubberband Test"; + } + public Panel centerPanel() { + return new RubberbandTestPanel(); + } +} + +class RubberbandTestPanel extends Panel { + private DrawingPanel drawingPanel; + private ChoicePanel choicePanel; + + public RubberbandTestPanel() { + drawingPanel = new DrawingPanel(); + choicePanel = new ChoicePanel(drawingPanel); + + setLayout(new BorderLayout()); + add("North", choicePanel); + add("Center", drawingPanel); + } +} + +class ChoicePanel extends Panel { + private DrawingPanel drawingPanel; + private Color color; + private Checkbox fillCheckbox = new Checkbox(); + + public ChoicePanel(DrawingPanel drawingPanel) { + Panel choicePanel = new Panel(); + Choice geometricChoice = new Choice(); + Choice colorChoice = new Choice(); + + this.drawingPanel = drawingPanel; + + geometricChoice.addItem("Lines"); + geometricChoice.addItem("Rectangles"); + geometricChoice.addItem("Ellipses"); + + colorChoice.addItem("Black"); + colorChoice.addItem("Red"); + colorChoice.addItem("Blue"); + colorChoice.addItem("Gray"); + colorChoice.addItem("White"); + + choicePanel.setLayout(new RowLayout(10)); + choicePanel.add(new Label("Shape:")); + choicePanel.add(geometricChoice); + choicePanel.add(new Label("Color:")); + choicePanel.add(colorChoice); + choicePanel.add(new Label("Fill:")); + choicePanel.add(fillCheckbox); + + setLayout(new BorderLayout()); + add("Center", choicePanel); + add("South", new Separator()); + } + public boolean action(Event event, Object what) { + if(event.target instanceof Checkbox) { + drawingPanel.setFill(fillCheckbox.getState()); + } + else if(event.target instanceof Choice) { + if(((String)what).equals("Lines")) { + fillCheckbox.setState(false); + drawingPanel.drawLines(); + } + else if(((String)what).equals("Rectangles")) { + System.out.println("Rectangles"); + drawingPanel.drawRectangles(); + } + else if(((String)what).equals("Ellipses")) + drawingPanel.drawEllipses (); + else if(((String)what).equals("Black")) + drawingPanel.setColor(Color.black); + else if(((String)what).equals("Red")) + drawingPanel.setColor(Color.red); + else if(((String)what).equals("Blue")) + drawingPanel.setColor(Color.blue); + else if(((String)what).equals("Gray")) + drawingPanel.setColor(Color.gray); + else if(((String)what).equals("White")) + drawingPanel.setColor(Color.white); + } + return true; + } + public Insets insets() { return new Insets(5,0,5,0); } +} diff --git a/java/gjt/test/SeparatorTest.java b/java/gjt/test/SeparatorTest.java new file mode 100644 index 00000000000..3dd80173ea3 --- /dev/null +++ b/java/gjt/test/SeparatorTest.java @@ -0,0 +1,64 @@ +package gjt.test; + +import java.awt.*; +import gjt.Etching; +import gjt.Separator; + +/** + * Two Separators, one horizontal and the other vertical, the + * former etched in, and the latter etched out are laid out with + * an adorning Label for each.<p> + * + * @version 1.0, April 25, 1996 + * @author David Geary + * @see gjt.UnitTest + * @see gjt.Separator + */ +public class SeparatorTest extends UnitTest { + public String title () { return "Separator Test"; } + public Panel centerPanel() { + return new SeparatorTestPanel(); + } +} + +class SeparatorTestPanel extends Panel { + public SeparatorTestPanel() { + setLayout(new BorderLayout()); + add("North", new SeparatorTestNorthPanel ()); + add("Center", new SeparatorTestCenterPanel()); + } +} + +class SeparatorTestNorthPanel extends Panel { + Separator separator = new Separator(); + + public SeparatorTestNorthPanel() { + setLayout(new BorderLayout()); + add("North", new Label("North Of Etched-In Separator")); + add("South", separator); + } +} + +class SeparatorTestCenterPanel extends Panel { + Separator separator = new Separator(Etching.OUT); + + public SeparatorTestCenterPanel() { + GridBagConstraints gbc = new GridBagConstraints(); + GridBagLayout gbl = new GridBagLayout(); + Label label = new Label("West Of Etched-Out Separator"); + + setLayout(gbl); + gbc.anchor = GridBagConstraints.WEST; + gbc.insets = new Insets(0,0,0,10); + gbl.setConstraints(label, gbc); + add(label); + + gbc.insets = new Insets(0,0,0,0); + gbc.weightx = 1.0; + gbc.weighty = 1.0; + gbc.fill = GridBagConstraints.VERTICAL; + gbl.setConstraints(separator, gbc); + add(separator); + + } +} diff --git a/java/gjt/test/SimpleAnimationTest.java b/java/gjt/test/SimpleAnimationTest.java new file mode 100644 index 00000000000..faf0c7c611c --- /dev/null +++ b/java/gjt/test/SimpleAnimationTest.java @@ -0,0 +1,87 @@ +package gjt.test; + +import java.net.URL; +import java.applet.Applet; +import java.awt.*; + +import gjt.Util; +import gjt.Orientation; +import gjt.animation.*; + +/** + * An animation playfield containing a lone sprite that bounces + * off the boundaries of the playfield.<p> + * + * @version 1.0, Apr 1 1996 + * @author David Geary + * @see gjt.test.AnimationTest + * @see gjt.animation.Playfield + * @see gjt.animation.Sprite + */ +public class SimpleAnimationTest extends UnitTest { + public String title() { + return "Simple Animation - Mouse Down Starts/Stops"; + } + public Panel centerPanel() { + return new SimpleAnimationTestPanel(this); + } +} + +class SimpleAnimationTestPanel extends Panel { + public SimpleAnimationTestPanel(Applet applet) { + setLayout(new BorderLayout()); + add("Center", new SimplePlayfield(applet)); + } +} + +class SimplePlayfield extends Playfield { + private Applet applet; + private URL cb; + private Sprite javaDrinker; + private Sequence spinSequence; + + public SimplePlayfield(Applet applet) { + this.applet = applet; + cb = applet.getCodeBase(); + makeSequencesAndSprites(); + } + public void paintBackground(Graphics g) { + Image bg = applet.getImage(cb, "gifs/background.gif"); + Util.wallPaper(this, g, bg); + } + public boolean mouseDown(Event event, int x, int y) { + if(running() == true) stop (); + else start(); + return true; + } + public void spriteCollision(Sprite sprite, Sprite sprite2) { + // Nothing to do: only 1 sprite! + } + public void edgeCollision(Sprite sprite, + Orientation orientation) { + if(orientation == Orientation.RIGHT || + orientation == Orientation.LEFT) + sprite.reverseX(); + else + sprite.reverseY(); + } + private void makeSequencesAndSprites() { + String file; + Point startLoc = new Point(10, 10); + Image[] spinImages = new Image[19]; + + for(int i=0; i < spinImages.length; ++i) { + file = "gifs/spin"; + + if(i < 10) file += "0" + i + ".gif"; + else file += i + ".gif"; + + spinImages[i] = applet.getImage(cb, file); + } + spinSequence = new Sequence(this, spinImages); + javaDrinker = new Sprite(this, spinSequence, startLoc); + + javaDrinker.setMoveVector(new Point(2,2)); + addSprite(javaDrinker); + } +} diff --git a/java/gjt/test/SimpleBargaugeTest.java b/java/gjt/test/SimpleBargaugeTest.java new file mode 100644 index 00000000000..57eb464f4b1 --- /dev/null +++ b/java/gjt/test/SimpleBargaugeTest.java @@ -0,0 +1,61 @@ +package gjt.test; + +import java.awt.*; +import gjt.Bargauge; + +/** + * A lone Barguage which animates. This unit test is meant to + * illustrate that a Bargauge can cope with having its + * orientation chanaged from horizontal to vertical or + * vice-versa. This test is best run in appletviewer, so that + * the window may be resized such that the Bargauge changes its + * orientation.<p> + * + * <em> + * Warning: An AWT bug causes this test to be a gluttenous + * consumer of resources (especially under Win95). A mouse down + * will halt the animation thread along with its consumption of + * resources.<p> + * </em> + * + * @version 1.0, April 25, 1996 + * @author David Geary + * @see gjt.test.UnitTest + * @see gjt.Bargauge + */ +public class SimpleBargaugeTest extends UnitTest { + public String title() { + return "Simple Bargauge Test"; + } + public Panel centerPanel() { + return new SimpleBargaugeTestPanel(); + } +} + +class SimpleBargaugeTestPanel extends Panel implements Runnable { + private Bargauge gauge = new Bargauge(Color.blue); + private boolean running = true; + private Thread t; + + public SimpleBargaugeTestPanel() { + setLayout(new BorderLayout()); + add("Center", gauge); + + t = new Thread(this); + t.start(); + } + public void run() { + while(true) { + try { Thread.currentThread().sleep(500,0); } + catch(InterruptedException e) { } + + gauge.setFillPercent(Math.random() * 100); + gauge.fill(); + } + } + public boolean mouseDown(Event event, int x, int y) { + if(running) { t.suspend(); running = false; } + else { t.resume (); running = true; } + return true; + } +} diff --git a/java/gjt/test/StateButtonTest.java b/java/gjt/test/StateButtonTest.java new file mode 100644 index 00000000000..508aee1682e --- /dev/null +++ b/java/gjt/test/StateButtonTest.java @@ -0,0 +1,41 @@ +package gjt.test; + +import java.applet.Applet; +import java.awt.*; +import java.net.URL; +import gjt.StateButton; +import gjt.ImageButtonEvent; + +/** + * A StateButton which cycles through a fascinating series of + * Images.<p> + * + * @version 1.0, April 25, 1996 + * @author David Geary + * @see gjt.test.UnitTest + * @see gjt.StateButton + */ +public class StateButtonTest extends UnitTest { + public String title () { return "StateButton Test"; } + public Panel centerPanel() { + return new StateButtonTestPanel(this); + } +} + +class StateButtonTestPanel extends Panel { + private URL codeBase; + private Image[] images; + private StateButton button; + + public StateButtonTestPanel(Applet applet) { + codeBase = applet.getCodeBase(); + images = new Image[3]; + images[0] = applet.getImage(codeBase, "gifs/fly.gif"); + images[1] = applet.getImage(codeBase, "gifs/frog.gif"); + images[2] = applet.getImage(codeBase, "gifs/eagle.gif"); + button = new StateButton(images); + + setLayout(new FlowLayout(FlowLayout.CENTER, 20, 20)); + add (button); + } +} diff --git a/java/gjt/test/TenPixelBorder.java b/java/gjt/test/TenPixelBorder.java new file mode 100644 index 00000000000..bab694d0fb1 --- /dev/null +++ b/java/gjt/test/TenPixelBorder.java @@ -0,0 +1,44 @@ +package gjt.test; + +import java.awt.*; + +public class TenPixelBorder extends Panel { + public TenPixelBorder(Component borderMe) { + setLayout(new BorderLayout()); + add("Center", borderMe); + } + public void paint(Graphics g) { + Dimension mySize = size(); + Insets myInsets = insets(); + + g.setColor(Color.gray); + + // Top Inset area + g.fillRect(0, + 0, + mySize.width, + myInsets.top); + + // Left Inset area + g.fillRect(0, + 0, + myInsets.left, + mySize.height); + + // Right Inset area + g.fillRect(mySize.width - myInsets.right, + 0, + myInsets.right, + mySize.height); + + // Bottom Inset area + g.fillRect(0, + mySize.height - myInsets.bottom, + mySize.width, + mySize.height); + } + public Insets insets() { + return new Insets(10,10,10,10); + } + +} diff --git a/java/gjt/test/TitledPanel.java b/java/gjt/test/TitledPanel.java new file mode 100644 index 00000000000..cb8d054e888 --- /dev/null +++ b/java/gjt/test/TitledPanel.java @@ -0,0 +1,22 @@ +package gjt.test; + +import java.awt.BorderLayout; +import java.awt.Label; +import java.awt.Panel; +import gjt.Separator; + +/** + * A Panel fitted with a BorderLayout that contains a Label + * (title) in the North, and a Separator in the South. + * + * @version 1.0, Apr 2 1996 + * @author David Geary + */ + +public class TitledPanel extends Panel { + public TitledPanel(String title) { + setLayout(new BorderLayout()); + add("North", new Label(title, Label.CENTER)); + add("South", new Separator()); + } +} diff --git a/java/gjt/test/ToolbarTest.java b/java/gjt/test/ToolbarTest.java new file mode 100644 index 00000000000..f739ce96236 --- /dev/null +++ b/java/gjt/test/ToolbarTest.java @@ -0,0 +1,111 @@ +package gjt.test; + +import java.net.URL; +import java.awt.*; +import java.applet.Applet; +import gjt.ExclusiveImageButtonPanel; +import gjt.ImageButton; +import gjt.ImageButtonEvent; +import gjt.Orientation; +import gjt.Toolbar; +import gjt.Separator; + +/** + * A Toolbar to the north, and an ExclusiveImageButtonPanel on + * the west give this little applet its own unique charm. + * Owner is motivated.<p> + * + * @version 1.0, April 25, 1996 + * @author David Geary + * @see gjt.test.UnitTest + * @see gjt.ExclusiveImageButtonPanel + * @see gjt.ImageButton + * @see gjt.Toolbar + */ +public class ToolbarTest extends UnitTest { + public String title() { + return "Toolbar/ImageButtonPanel Test"; + } + public Panel centerPanel() { + return new ToolbarTestPanel(this); + } +} + +class ToolbarTestPanel extends Panel { + ImageButton newButton, openButton, diskButton, + printButton, cutButton, copyButton, + pasteButton; + + public ToolbarTestPanel(Applet app) { + setLayout(new BorderLayout()); + add("North", makeToolbar(app, app.getCodeBase())); + add("West", makePalette(app, app.getCodeBase())); + } + public boolean handleEvent(Event event) { + if(event instanceof ImageButtonEvent) { + ImageButtonEvent ibevent = (ImageButtonEvent)event; + + if(ibevent.isActivated()) { + if(event.target == newButton) + System.out.println("New Button Activated"); + if(event.target == openButton) + System.out.println("Open Button Activated"); + if(event.target == diskButton) + System.out.println("Disk Button Activated"); + if(event.target == printButton) + System.out.println("Print Button Activated"); + if(event.target == cutButton) + System.out.println("Cut Button Activated"); + if(event.target == copyButton) + System.out.println("Copy Button Activated"); + if(event.target == pasteButton) + System.out.println("Paste Button Activated"); + + return true; + } + } + + return super.handleEvent(event); + } + private Toolbar makeToolbar(Applet app, URL cb) { + Toolbar tb = new Toolbar(10, 0); + + newButton = tb.add(app.getImage(cb, "gifs/new.gif")); + openButton = tb.add(app.getImage(cb, "gifs/open.gif")); + diskButton = tb.add(app.getImage(cb, "gifs/disk.gif")); + + tb.addSpacer(newButton.preferredSize().width); + + printButton = tb.add(app.getImage(cb, "gifs/print.gif")); + + tb.addSpacer(newButton.preferredSize().width); + + cutButton = tb.add(app.getImage(cb, "gifs/cut.gif")); + copyButton = tb.add(app.getImage(cb, "gifs/copy.gif")); + pasteButton = tb.add(app.getImage(cb, "gifs/paste.gif")); + + return tb; + } + private Panel makePalette(Applet app, URL cb) { + ExclusiveImageButtonPanel iconPalette; + Panel iconPalettePanel = new Panel(); + + iconPalette = new ExclusiveImageButtonPanel( + Orientation.VERTICAL, + Orientation.CENTER, + Orientation.TOP, 10); + + iconPalette.add(app.getImage(cb,"gifs/ballot_box.gif")); + iconPalette.add(app.getImage(cb,"gifs/palette.gif")); + iconPalette.add(app.getImage(cb,"gifs/light_bulb1.gif")); + iconPalette.add(app.getImage(cb,"gifs/Dining.gif")); + iconPalette.add(app.getImage(cb,"gifs/scissors.gif")); + iconPalette.add(app.getImage(cb,"gifs/tricycle.gif")); + + iconPalettePanel = new Panel(); + iconPalettePanel.setLayout(new BorderLayout()); + iconPalettePanel.add ("Center", iconPalette); + iconPalettePanel.add ("East", new Separator()); + return iconPalettePanel; + } +} diff --git a/java/gjt/test/TwoDrinkersAnimationTest.java b/java/gjt/test/TwoDrinkersAnimationTest.java new file mode 100644 index 00000000000..ae4041b9eb6 --- /dev/null +++ b/java/gjt/test/TwoDrinkersAnimationTest.java @@ -0,0 +1,130 @@ +package gjt.test; + +import java.net.URL; +import java.applet.Applet; +import java.awt.*; +import java.awt.Panel; + +import gjt.Util; +import gjt.Orientation; +import gjt.animation.*; + +/** + * An animation playfield containing two "java drinkers", that + * both bounce off the sides of the playfield.<p> + * + * One of the java drinkers moves slow and spins fast, while + * the other java drinker moves fast and spins slow. When + * the two java drinkers collide, they both play a bump + * sequence - at different speeds.<p> + * + * @version 1.0, Apr 1 1996 + * @author David Geary + * @see gjt.test.AnimationTest + * @see gjt.animation.Playfield + * @see gjt.animation.Sprite + */ +public class TwoDrinkersAnimationTest extends UnitTest { + public String title() { + return + "TwoDrinkers Animation - Mouse Down Starts/Stops"; + } + public Panel centerPanel() { + return new TwoDrinkersAnimationTestPanel(this); + } +} + +class TwoDrinkersAnimationTestPanel extends Panel { + public TwoDrinkersAnimationTestPanel(Applet applet) { + setLayout(new BorderLayout()); + add("Center", new TwoDrinkersPlayfield(applet)); + } +} + +class TwoDrinkersPlayfield extends Playfield { + private Applet applet; + private URL cb; + private Sprite moveFastSpinSlow, moveSlowSpinFast; + private Sequence fastSpinSequence, + slowSpinSequence, + fastBumpSequence, + slowBumpSequence; + + public TwoDrinkersPlayfield(Applet applet) { + this.applet = applet; + cb = applet.getCodeBase(); + makeSequencesAndSprites(); + } + public void paintBackground(Graphics g) { + Image bg = applet.getImage(cb, "gifs/background.gif"); + Util.wallPaper(this, g, bg); + } + public boolean mouseDown(Event event, int x, int y) { + if(running() == true) stop (); + else start(); + return true; + } + public void spriteCollision(Sprite sprite, Sprite sprite2) { + if(moveSlowSpinFast.getSequence() != fastBumpSequence) { + sprite.reverse(); + sprite2.reverse(); + + moveSlowSpinFast.play(fastBumpSequence, 3); + moveFastSpinSlow.play(slowBumpSequence, 3); + } + } + public void edgeCollision(Sprite sprite, + Orientation orientation) { + if(orientation == Orientation.RIGHT || + orientation == Orientation.LEFT) + sprite.reverseX(); + else + sprite.reverseY(); + } + private void makeSequencesAndSprites() { + String file; + Image[] spinImages = new Image[19]; + Image[] bumpImages = new Image[6]; + Image[] volleyball = new Image[4]; + + for(int i=0; i < spinImages.length; ++i) { + file = "gifs/spin"; + + if(i < 10) file += "0" + i + ".gif"; + else file += i + ".gif"; + + spinImages[i] = applet.getImage(cb, file); + } + for(int i=0; i < bumpImages.length; ++i) { + file = "gifs/bump0" + i + ".gif"; + bumpImages[i] = applet.getImage(cb, file); + } + fastSpinSequence = new Sequence(this, spinImages); + slowSpinSequence = new Sequence(this, spinImages); + + fastBumpSequence = new Sequence(this, bumpImages); + slowBumpSequence = new Sequence(this, bumpImages); + + moveFastSpinSlow = + new Sprite(this, + slowSpinSequence, new Point(25, 75)); + + moveSlowSpinFast = + new Sprite(this, + fastSpinSequence, new Point(250,250)); + + fastSpinSequence.setAdvanceInterval(50); + slowSpinSequence.setAdvanceInterval(300); + + fastBumpSequence.setAdvanceInterval(25); + slowBumpSequence.setAdvanceInterval(200); + + moveFastSpinSlow.setMoveVector(new Point(2,3)); + moveSlowSpinFast.setMoveVector(new Point(-1,-1)); + + moveSlowSpinFast.setMoveInterval(100); + + addSprite(moveFastSpinSlow); + addSprite(moveSlowSpinFast); + } +} diff --git a/java/gjt/test/UnitTest.java b/java/gjt/test/UnitTest.java new file mode 100644 index 00000000000..1fa262d5629 --- /dev/null +++ b/java/gjt/test/UnitTest.java @@ -0,0 +1,46 @@ +package gjt.test; + +import java.awt.BorderLayout; +import java.awt.Frame; +import java.awt.Panel; +import java.applet.Applet; +import gjt.*; + +/** + * An (abstract) Applet fitted with a BorderLayout that + * contains a TitledPanel in the North, and a Panel created by + * derived classes in the Center.<p> + * + * Since some Applets take awhile to load, UnitTest changes the + * cursor to a wait cursor in init(), changing it back to the + * default cursor in start(). Derived classes must be sure to + * call super.init() if they override init(); likewise for + * start().<p> + * + * Subclasses must implement: + * <dl> + * <dd>String title() + * <dd>Panel centerPanel() + * </dl> + * Subclasses should populate the Panel returned from + * centerPanel() with whatever makes sense for their unit test. + * + * @version 1.0, April 25, 1996 + * @author David Geary + * @see TitledPanel + */ +abstract public class UnitTest extends Applet { + abstract public String title(); + abstract public Panel centerPanel(); + + public void init() { + Util.getFrame(this).setCursor(Frame.WAIT_CURSOR); + Panel titledPanel = new TitledPanel(title()); + setLayout(new BorderLayout()); + add("North", titledPanel); + add("Center", centerPanel()); + } + public void start() { + Util.getFrame(this).setCursor(Frame.DEFAULT_CURSOR); + } +} |