summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--java/gjt/Assert.java33
-rw-r--r--java/gjt/Bargauge.java80
-rw-r--r--java/gjt/Border.java105
-rw-r--r--java/gjt/Box.java81
-rw-r--r--java/gjt/BulletinLayout.java100
-rw-r--r--java/gjt/ButtonPanel.java51
-rw-r--r--java/gjt/CardPanel.java48
-rw-r--r--java/gjt/ChoiceCardPanel.java53
-rw-r--r--java/gjt/ColumnLayout.java154
-rw-r--r--java/gjt/ComponentScroller.java42
-rw-r--r--java/gjt/DialogClient.java20
-rw-r--r--java/gjt/DrawingPanel.java72
-rw-r--r--java/gjt/DrawnRectangle.java136
-rw-r--r--java/gjt/EtchedBorder.java59
-rw-r--r--java/gjt/EtchedRectangle.java97
-rw-r--r--java/gjt/Etching.java22
-rw-r--r--java/gjt/ExclusiveImageButtonPanel.java47
-rw-r--r--java/gjt/FontDialog.java362
-rw-r--r--java/gjt/GJTDialog.java51
-rw-r--r--java/gjt/IconCardPanel.java55
-rw-r--r--java/gjt/ImageButton.java209
-rw-r--r--java/gjt/ImageButtonController.java79
-rw-r--r--java/gjt/ImageButtonEvent.java103
-rw-r--r--java/gjt/ImageButtonPanel.java106
-rw-r--r--java/gjt/ImageButtonPanelController.java47
-rw-r--r--java/gjt/ImageCanvas.java31
-rw-r--r--java/gjt/ImageScroller.java62
-rw-r--r--java/gjt/LabelCanvas.java93
-rw-r--r--java/gjt/MessageDialog.java77
-rw-r--r--java/gjt/MouseController.java32
-rw-r--r--java/gjt/Orientation.java87
-rw-r--r--java/gjt/ProgressDialog.java67
-rw-r--r--java/gjt/QuestionDialog.java130
-rw-r--r--java/gjt/RadioImageButtonPanelController.java45
-rw-r--r--java/gjt/RowLayout.java153
-rw-r--r--java/gjt/Scroller.java154
-rw-r--r--java/gjt/ScrollerLayout.java160
-rw-r--r--java/gjt/SelectionEvent.java82
-rw-r--r--java/gjt/Separator.java90
-rw-r--r--java/gjt/SpringyImageButtonController.java54
-rw-r--r--java/gjt/StateButton.java45
-rw-r--r--java/gjt/StateButtonController.java27
-rw-r--r--java/gjt/StickyImageButtonController.java87
-rw-r--r--java/gjt/Stopwatch.java94
-rw-r--r--java/gjt/StopwatchClient.java14
-rw-r--r--java/gjt/ThreeDBorder.java53
-rw-r--r--java/gjt/ThreeDBorderStyle.java24
-rw-r--r--java/gjt/ThreeDRectangle.java105
-rw-r--r--java/gjt/Toolbar.java58
-rw-r--r--java/gjt/Util.java69
-rw-r--r--java/gjt/YesNoDialog.java80
-rw-r--r--java/gjt/animation/CollisionArena.java39
-rw-r--r--java/gjt/animation/CollisionDetector.java24
-rw-r--r--java/gjt/animation/EdgeCollisionDetector.java53
-rw-r--r--java/gjt/animation/Playfield.java140
-rw-r--r--java/gjt/animation/Sequence.java119
-rw-r--r--java/gjt/animation/Sprite.java191
-rw-r--r--java/gjt/animation/SpriteCollisionDetector.java45
-rw-r--r--java/gjt/image/BleachImageFilter.java53
-rw-r--r--java/gjt/image/DissolveFilter.java48
-rw-r--r--java/gjt/image/ImageDissolver.java132
-rw-r--r--java/gjt/rubberband/Rubberband.java100
-rw-r--r--java/gjt/rubberband/RubberbandEllipse.java32
-rw-r--r--java/gjt/rubberband/RubberbandLine.java25
-rw-r--r--java/gjt/rubberband/RubberbandPanel.java38
-rw-r--r--java/gjt/rubberband/RubberbandRectangle.java29
-rw-r--r--java/gjt/test/AttributesPanel.java78
-rw-r--r--java/gjt/test/BargaugeTest.java130
-rw-r--r--java/gjt/test/BleachImageFilterTest.java86
-rw-r--r--java/gjt/test/BorderTest.java202
-rw-r--r--java/gjt/test/BoxTest.java100
-rw-r--r--java/gjt/test/BumpAnimationTest.java107
-rw-r--r--java/gjt/test/ChoiceCardPanelTest.java34
-rw-r--r--java/gjt/test/ColumnLayoutTest.java126
-rw-r--r--java/gjt/test/ComponentScrollerTest.java205
-rw-r--r--java/gjt/test/ConnectionsPanel.java9
-rw-r--r--java/gjt/test/DialogTest.java140
-rw-r--r--java/gjt/test/DrawnRectangleTest.java119
-rw-r--r--java/gjt/test/FontDialogTest.java95
-rw-r--r--java/gjt/test/IconCardPanelTest.java47
-rw-r--r--java/gjt/test/ImageButtonTest.java130
-rw-r--r--java/gjt/test/ImageDissolverTest.java69
-rw-r--r--java/gjt/test/ImageScrollerTest.java55
-rw-r--r--java/gjt/test/LabelCanvasTest.java75
-rw-r--r--java/gjt/test/MessageDialogTest.java50
-rw-r--r--java/gjt/test/OccupationOracle.java334
-rw-r--r--java/gjt/test/RowLayoutTest.java124
-rw-r--r--java/gjt/test/RubberbandTest.java112
-rw-r--r--java/gjt/test/SeparatorTest.java64
-rw-r--r--java/gjt/test/SimpleAnimationTest.java87
-rw-r--r--java/gjt/test/SimpleBargaugeTest.java61
-rw-r--r--java/gjt/test/StateButtonTest.java41
-rw-r--r--java/gjt/test/TenPixelBorder.java44
-rw-r--r--java/gjt/test/TitledPanel.java22
-rw-r--r--java/gjt/test/ToolbarTest.java111
-rw-r--r--java/gjt/test/TwoDrinkersAnimationTest.java130
-rw-r--r--java/gjt/test/UnitTest.java46
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);
+ }
+}