diff --git a/pom.xml b/pom.xml index 2bcfe59b24..aee328328b 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ com.squidpony squidlib - 1.95 + 1.95.1 jar @@ -57,12 +57,6 @@ UTF-8 UTF-8 - - - gdx-nightlies - https://oss.sonatype.org/content/repositories/snapshots/ - - @@ -75,20 +69,6 @@ - - com.googlecode.mavennatives - maven-nativedependencies-plugin - 0.0.7 - - - unpacknatives - - copy - - - - - org.apache.maven.plugins maven-gpg-plugin @@ -103,18 +83,69 @@ + + + maven-source-plugin + 2.1.2 + + + package-jars + package + + jar + test-jar + + + true + + + + + true + + + + + maven-javadoc-plugin + 2.8 + true + + + package-jars + package + + jar + test-jar + + + true + + + + + true + 128m + 1024m + true + ${project.name} ${project.version} + ${project.name} ${project.version} + ${project.name} ${project.version} (TEST API) + ${project.name} ${project.version} (TEST API) + true + ${project.build.sourceEncoding} + + http://java.sun.com/j2se/1.6.0/docs/api + http://java.sun.com/j2se/1.5.0/docs/api + http://java.sun.com/j2se/1.4.2/docs/api + http://java.sun.com/j2ee/1.4/docs/api + + true + false + + + - - com.badlogicgames.gdx - gdx - 0.9.9-SNAPSHOT - - - com.badlogicgames.gdx - gdx-backend-lwjgl - 0.9.9-SNAPSHOT - diff --git a/pom.xml.releaseBackup b/pom.xml.releaseBackup new file mode 100644 index 0000000000..2de7adef22 --- /dev/null +++ b/pom.xml.releaseBackup @@ -0,0 +1,120 @@ + + 4.0.0 + + com.squidpony + squidlib + 1.95-SNAPSHOT + jar + + + org.sonatype.oss + oss-parent + 7 + + + SquidLib + Please refer to https://github.com/SquidPony/SquidLib . + + https://github.com/SquidPony/SquidLib + + + + Eben Howard ( https://github.com/SquidPony ) + example@example.com + + + + + + Apache Public License + + https://www.apache.org/licenses/LICENSE-2.0.html + + LICENSE.txt + repo + + + + 2012 + + + 3.0.3 + + + + https://github.com/SquidPony/SquidLib/issues + GitHub Issues + + + + scm:git:git@github.com:tommyettinger/SquidLib.git + scm:git:git@github.com:tommyettinger/SquidLib.git + git@github.com:tommyettinger/SquidLib.git + + + + UTF-8 + UTF-8 + UTF-8 + + + + gdx-nightlies + https://oss.sonatype.org/content/repositories/snapshots/ + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.0 + + 1.7 + 1.7 + + + + + com.googlecode.mavennatives + maven-nativedependencies-plugin + 0.0.7 + + + unpacknatives + + copy + + + + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.4 + + + sign-artifacts + verify + + sign + + + + + + + + + com.badlogicgames.gdx + gdx + 0.9.9-SNAPSHOT + + + com.badlogicgames.gdx + gdx-backend-lwjgl + 0.9.9-SNAPSHOT + + + diff --git a/release.properties b/release.properties new file mode 100644 index 0000000000..fc71a46d57 --- /dev/null +++ b/release.properties @@ -0,0 +1,21 @@ +#release configuration +#Fri Jul 26 03:48:22 PDT 2013 +scm.commentPrefix=[maven-release-plugin] +pushChanges=true +dependency.dependency.com.badlogicgames.gdx\:gdx.development=0.9.9-SNAPSHOT +project.scm.com.squidpony\:squidlib.tag=HEAD +dependency.dependency.com.badlogicgames.gdx\:gdx.release=0.9.9-SNAPSHOT +scm.tag=squidlib-1.95 +project.dev.com.squidpony\:squidlib=1.96-SNAPSHOT +remoteTagging=true +exec.additionalArguments=-Psonatype-oss-release +project.scm.com.squidpony\:squidlib.developerConnection=scm\:git\:git@github.com\:tommyettinger/SquidLib.git +project.scm.com.squidpony\:squidlib.url=git@github.com\:tommyettinger/SquidLib.git +scm.url=scm\:git\:git@github.com\:tommyettinger/SquidLib.git +preparationGoals=clean verify +dependency.dependency.com.badlogicgames.gdx\:gdx-backend-lwjgl.development=0.9.9-SNAPSHOT +scm.username=tommyettinger +project.rel.com.squidpony\:squidlib=1.95 +dependency.dependency.com.badlogicgames.gdx\:gdx-backend-lwjgl.release=0.9.9-SNAPSHOT +project.scm.com.squidpony\:squidlib.connection=scm\:git\:git@github.com\:tommyettinger/SquidLib.git +completedPhase=run-preparation-goals diff --git a/src/main/java/squidpony/annotation/Beta.java b/src/main/java/squidpony/annotation/Beta.java new file mode 100644 index 0000000000..7cabb16d3a --- /dev/null +++ b/src/main/java/squidpony/annotation/Beta.java @@ -0,0 +1,27 @@ +package squidpony.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Signifies that a public API (public class, method or field) is subject to + * incompatible changes, or even removal, in a future release. An API bearing + * this annotation is exempt from any compatibility guarantees made by its + * containing library. + * + * @author Kevin Bourrillion + */ +@Retention(RetentionPolicy.CLASS) +@Target({ + ElementType.ANNOTATION_TYPE, + ElementType.CONSTRUCTOR, + ElementType.FIELD, + ElementType.METHOD, + ElementType.TYPE}) +@Documented +@Beta +public @interface Beta { +} diff --git a/src/main/java/squidpony/package.html b/src/main/java/squidpony/package.html new file mode 100644 index 0000000000..0651337648 --- /dev/null +++ b/src/main/java/squidpony/package.html @@ -0,0 +1,8 @@ + + + +

+ This is the base package for all components of the SquidLib Library. +

+ + diff --git a/src/main/java/squidpony/squidcolor/SColor.java b/src/main/java/squidpony/squidcolor/SColor.java index c369eb5855..afb8de0f99 100644 --- a/src/main/java/squidpony/squidcolor/SColor.java +++ b/src/main/java/squidpony/squidcolor/SColor.java @@ -1,6 +1,7 @@ package squidpony.squidcolor; import java.awt.Color; +import java.util.Objects; /** * Allows for the use of custom colors with custom names. @@ -8,12 +9,11 @@ * These colors are comparable for equality but the ordering of them is based on * their hex values. * - * Has some built in pallets available as SColor arrays. + * Has some built in palettes available as SColor arrays. * - * @author Eben Howard - http://squidpony.com + * @author Eben Howard - http://squidpony.com - howard@squidpony.com */ -public class SColor extends Color implements Comparable { - +public class SColor extends Color { private String name = "Unnamed"; /** * Color constant
             @ 
@@ -5416,41 +5416,6 @@ public SColor(int r, int g, int b, String name) {
         this.name = name;
     }
 
-    /**
-     * Compares the current color to another color. Comparison is not guaranteed
-     * to lead to a logical color ordering that may be expected.
-     *
-     * @param color new color to compare with current color
-     * @return indicator of comparison between colors
-     */
-    public int compareTo(SColor color) {
-        int compare = 0;//default to being equal
-        if (getRGB() < color.getRGB()) {
-            compare = -1;
-        } else if (getRGB() > color.getRGB()) {
-            compare = 1;
-        }
-        return compare;
-    }
-
-    /**
-     * Compares the current color to another object of any type. If the second
-     * object is not a SColor object than an exception will be thrown.
-     *
-     * @throws UnsupportedOperationException if second object not a SColor
-     * object
-     * @param arg0 second object to be compared to
-     * @return indicator of comparison between colors
-     */
-    @Override
-    public int compareTo(Object arg0) {
-        try {
-            return compareTo((SColor) arg0);
-        } catch (Exception e) {
-            throw new UnsupportedOperationException("Incorrect Object Type");
-        }
-    }
-
     @Override
     public String toString() {
         return name + " " + super.toString();
@@ -5459,4 +5424,17 @@ public String toString() {
     public String getName() {
         return name;
     }
+
+    @Override
+    public boolean equals(Object other) {
+        return other instanceof SColor || other instanceof Color ? this.getRGB() == ((Color) other).getRGB() : false;
+    }
+
+    @Override
+    public int hashCode() {
+        int hash = 5;
+        hash = 31 * hash + Objects.hashCode(this.name);
+        hash += 31 * hash + Objects.hashCode(this.getRGB());
+        return hash;
+    }
 }
diff --git a/src/main/java/squidpony/squidcolor/SColorChooserPanel.java b/src/main/java/squidpony/squidcolor/SColorChooserPanel.java
new file mode 100644
index 0000000000..e1f6e5831a
--- /dev/null
+++ b/src/main/java/squidpony/squidcolor/SColorChooserPanel.java
@@ -0,0 +1,271 @@
+package squidpony.squidcolor;
+
+import java.awt.AWTException;
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.Graphics;
+import java.awt.Rectangle;
+import java.awt.Robot;
+import java.awt.event.MouseEvent;
+import java.util.TreeMap;
+import javax.swing.DefaultComboBoxModel;
+import javax.swing.Icon;
+import javax.swing.JComboBox;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextField;
+import javax.swing.Scrollable;
+import javax.swing.SwingConstants;
+import javax.swing.colorchooser.AbstractColorChooserPanel;
+import javax.swing.event.MouseInputListener;
+
+/**
+ * This class provides a way to interact with the pre-defined SColor constants
+ * in a Swing GUI.
+ *
+ * @author Eben Howard - http://squidpony.com - howard@squidpony.com
+ */
+public class SColorChooserPanel extends AbstractColorChooserPanel {
+
+    private SColor[] colors = SColor.FULL_PALLET;
+    private TreeMap colorMap = new TreeMap<>();
+    private int colorHeight = 20;
+    private int colorWidth = 40;
+    private ColorPanel displayPanel = new ColorPanel();
+    private JScrollPane scrollPane = new JScrollPane();
+    private JComboBox colorComboBox = new JComboBox();
+    private JTextField colorName = new JTextField();
+
+    @Override
+    public void updateChooser() {
+    }
+
+    @Override
+    protected void buildChooser() {
+
+        scrollPane.setViewportView(displayPanel);
+        displayPanel.addMouseListener(displayPanel);
+        displayPanel.addMouseMotionListener(displayPanel);
+        colorComboBox.addActionListener(new java.awt.event.ActionListener() {
+            @Override
+            public void actionPerformed(java.awt.event.ActionEvent evt) {
+                colorComboBoxActionPerformed(evt);
+            }
+        });
+
+        colorMap.put("Achromatic Series", SColor.ACHROMATIC_SERIES);
+        colorMap.put("Blue Green Series", SColor.BLUE_GREEN_SERIES);
+        colorMap.put("Blue Violet Series", SColor.BLUE_VIOLET_SERIES);
+        colorMap.put("Full Pallet", SColor.FULL_PALLET);
+        colorMap.put("Rainbow", SColor.RAINBOW);
+        colorMap.put("Red Series", SColor.RED_SERIES);
+        colorMap.put("Red Violet Series", SColor.RED_VIOLET_SERIES);
+        colorMap.put("Violet Series", SColor.VIOLET_SERIES);
+        colorMap.put("Yellow Green Series", SColor.YELLOW_GREEN_SERIES);
+        colorMap.put("Yellow Red Series", SColor.YELLOW_RED_SERIES);
+        colorMap.put("Yellow Series", SColor.YELLOW_SERIES);
+
+        colorComboBox.setModel(new DefaultComboBoxModel(colorMap.keySet().toArray()));
+        setLayout(new BorderLayout());
+        add(colorComboBox, BorderLayout.NORTH);
+        add(scrollPane, BorderLayout.CENTER);
+        colorName.setEditable(false);
+        colorName.setHorizontalAlignment(JTextField.CENTER);
+        add(colorName, BorderLayout.SOUTH);
+    }
+
+    private void refreshPanel() {
+        scrollPane.getViewport().setViewSize(displayPanel.getPreferredScrollableViewportSize());
+        scrollPane.getViewport().revalidate();
+        repaint();
+    }
+
+    private void colorComboBoxActionPerformed(java.awt.event.ActionEvent evt) {
+        colors = colorMap.get((String) colorComboBox.getSelectedItem());
+        refreshPanel();
+    }
+
+    private void displayPanelMouseMoved(java.awt.event.MouseEvent evt) {
+        int index = evt.getY() / 20;
+        if (index < colors.length) {
+            String text = "";
+            switch (evt.getX() / colorWidth) {
+                case 0:
+                    text += "Fully Desaturated ";
+                    break;
+                case 1:
+                    text += "80% Desaturated ";
+                    break;
+                case 2:
+                    text += "Lightest ";
+                    break;
+                case 3:
+                    text += "Lighter ";
+                    break;
+                case 4:
+                    text += "Light ";
+                    break;
+                case 6:
+                    text += "Dim ";
+                    break;
+                case 7:
+                    text += "Dimmer ";
+                    break;
+                case 8:
+                    text += "Dimmest ";
+                    break;
+            }
+            text += colors[index].getName();
+//            displayPanel.setToolTipText(text);//don't need the tooltip with the display area
+            colorName.setText(text);
+        }
+    }
+
+    @Override
+    public String getDisplayName() {
+        return "SColor";
+    }
+
+    @Override
+    public Icon getSmallDisplayIcon() {
+        return null;
+    }
+
+    @Override
+    public Icon getLargeDisplayIcon() {
+        return null;
+    }
+
+    private class ColorPanel extends JPanel implements Scrollable, MouseInputListener {
+
+        ColorPanel() {
+            super(new FlowLayout());
+        }
+
+        @Override
+        public Dimension getPreferredSize() {
+            return new Dimension(colorWidth * 9, colorHeight * colors.length);
+        }
+
+        @Override
+        public void paintComponent(Graphics g) {
+            super.paintComponent(g);
+            int x = 0;
+            int y = 0;
+
+            g.setColor(SColor.WHITE);
+            g.fillRect(0, 0, getWidth(), colorHeight);
+
+            for (int i = 0; i < colors.length; i++) {
+                SColor color = colors[i];
+
+                g.setColor(SColorFactory.desaturated(color));
+                g.fillRect(x, y, colorWidth, colorHeight);
+                x += colorWidth;
+
+                g.setColor(SColorFactory.desaturate(color, 0.8));
+                g.fillRect(x, y, colorWidth, colorHeight);
+                x += colorWidth;
+
+                g.setColor(SColorFactory.lightest(color));
+                g.fillRect(x, y, colorWidth, colorHeight);
+                x += colorWidth;
+
+                g.setColor(SColorFactory.lighter(color));
+                g.fillRect(x, y, colorWidth, colorHeight);
+                x += colorWidth;
+
+
+                g.setColor(SColorFactory.light(color));
+                g.fillRect(x, y, colorWidth, colorHeight);
+                x += colorWidth;
+
+                g.setColor(color);
+                g.fillRect(x, y, colorWidth, colorHeight);
+                x += colorWidth;
+
+                g.setColor(SColorFactory.dim(color));
+                g.fillRect(x, y, colorWidth, colorHeight);
+                x += colorWidth;
+
+                g.setColor(SColorFactory.dimmer(color));
+                g.fillRect(x, y, colorWidth, colorHeight);
+                x += colorWidth;
+
+                g.setColor(SColorFactory.dimmest(color));
+                g.fillRect(x, y, getWidth() - x, colorHeight);//last column fills out the rest of the space
+
+                x = 0;
+                y += colorHeight;
+            }
+        }
+
+        @Override
+        public Dimension getPreferredScrollableViewportSize() {
+            return new Dimension(colorWidth * 9, Math.min(400, colorHeight * colors.length));
+        }
+
+        @Override
+        public int getScrollableUnitIncrement(Rectangle rctngl, int i, int i1) {
+            if (i == SwingConstants.VERTICAL) {
+                return colorHeight;
+            } else {
+                return colorWidth;
+            }
+        }
+
+        @Override
+        public int getScrollableBlockIncrement(Rectangle rctngl, int i, int i1) {
+            if (i == SwingConstants.VERTICAL) {
+                return colorHeight * 5;
+            } else {
+                return colorWidth * 3;
+            }
+        }
+
+        @Override
+        public boolean getScrollableTracksViewportWidth() {
+            return false;
+        }
+
+        @Override
+        public boolean getScrollableTracksViewportHeight() {
+            return false;
+        }
+
+        @Override
+        public void mouseClicked(MouseEvent e) {
+            try {
+                Robot robot = new Robot();
+                getColorSelectionModel().setSelectedColor(robot.getPixelColor(e.getXOnScreen(), e.getYOnScreen()));
+            } catch (AWTException ex) {
+            }
+        }
+
+        @Override
+        public void mousePressed(MouseEvent e) {
+        }
+
+        @Override
+        public void mouseReleased(MouseEvent e) {
+        }
+
+        @Override
+        public void mouseEntered(MouseEvent e) {
+        }
+
+        @Override
+        public void mouseExited(MouseEvent e) {
+        }
+
+        @Override
+        public void mouseDragged(MouseEvent e) {
+        }
+
+        @Override
+        public void mouseMoved(MouseEvent e) {
+            displayPanelMouseMoved(e);
+        }
+    }
+}
diff --git a/src/main/java/squidpony/squidcolor/SColorFactory.java b/src/main/java/squidpony/squidcolor/SColorFactory.java
index d49fec7f61..b709d63a3f 100644
--- a/src/main/java/squidpony/squidcolor/SColorFactory.java
+++ b/src/main/java/squidpony/squidcolor/SColorFactory.java
@@ -1,9 +1,17 @@
 package squidpony.squidcolor;
 
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Queue;
+import java.util.TreeMap;
+import javax.swing.JColorChooser;
+import javax.swing.JDialog;
+import javax.swing.colorchooser.AbstractColorChooserPanel;
 import squidpony.squidmath.Bresenham;
 import squidpony.squidmath.Point3D;
 import squidpony.squidmath.RNG;
@@ -15,14 +23,16 @@
  * All returned SColor objects are cached so multiple requests for the same
  * SColor will not create duplicate long term objects.
  *
- * @author Eben Howard - http://squidpony.com
+ * @author Eben Howard - http://squidpony.com - howard@squidpony.com
  */
 public class SColorFactory {
 
+    private static final TreeMap nameLookup = new TreeMap<>();
+    private static final TreeMap valueLookup = new TreeMap<>();
     private static RNG rng = new RNG();
     private static Map colorBag = new HashMap<>();
     private static Map> pallets = new HashMap<>();
-    private static int flooring = 1;//what multiple to floor rgb values to in order to reduce total colors
+    private static int floor = 1;//what multiple to floor rgb values to in order to reduce total colors
 
     /**
      * Prevents any instances from being created.
@@ -30,12 +40,53 @@ public class SColorFactory {
     private SColorFactory() {
     }
 
+    /**
+     * Returns the SColor Constant who's name is the one provided. If one cannot
+     * be found then null is returned.
+     *
+     * This method constructs a list of the SColor constants the first time it
+     * is called.
+     *
+     * @param s
+     * @return
+     */
+    public static SColor colorForName(String s) {
+        if (nameLookup.isEmpty()) {
+            for (SColor sc : SColor.FULL_PALLET) {
+                nameLookup.put(sc.getName(), sc);
+            }
+        }
+
+        return nameLookup.get(s);
+    }
+
+    /**
+     * Returns the SColor who's value matches the one passed in. If no SColor
+     * Constant matches that value then a cached or new SColor is returned that
+     * matches the provided value.
+     *
+     * This method constructs a list of the SColor constants the first time it
+     * is called.
+     *
+     * @param rgb
+     * @return
+     */
+    public static SColor colorForValue(int rgb) {
+        if (valueLookup.isEmpty()) {
+            for (SColor sc : SColor.FULL_PALLET) {
+                valueLookup.put(sc.getRGB(), sc);
+            }
+        }
+
+        return valueLookup.containsKey(rgb) ? valueLookup.get(rgb) : asSColor(rgb);
+    }
+
     /**
      * Returns the number of SColor objects currently cached.
      *
      * @return
      */
-    public static int getQuantityCached() {
+    public static int quantityCached() {
         return colorBag.size();
     }
 
@@ -64,7 +115,7 @@ private static int blend(int a, int b, double coef) {
      * @return
      */
     public static SColor blend(SColor color1, SColor color2, double coef) {
-        return getSColor(blend(color1.getRed(), color2.getRed(), coef),
+        return asSColor(blend(color1.getRed(), color2.getRed(), coef),
                 blend(color1.getGreen(), color2.getGreen(), coef),
                 blend(color1.getBlue(), color2.getBlue(), coef));
     }
@@ -107,8 +158,8 @@ public static void emptyCache() {
      *
      * @param value
      */
-    public static void setRGBFloorValue(int value) {
-        flooring = Math.max(1, value);
+    public static void setFloor(int value) {
+        floor = Math.max(1, value);
     }
 
     /**
@@ -117,25 +168,29 @@ public static void setRGBFloorValue(int value) {
      * If the color is not already in the cache, it is created and added to the
      * cache.
      *
+     * This method does not check to see if the value is already available as a
+     * SColor constant. If such functionality is desired then please use
+     * colorForValue(int rgb) instead.
+     *
      * @param rgb
      * @return
      */
-    public static SColor getSColor(int rgb) {
-        if (flooring != 1) {//need to convert to floored values
+    public static SColor asSColor(int rgb) {
+        if (floor != 1) {//need to convert to floored values
             int a = (rgb >> 24) & 0xff;
-            a -= a % flooring;
+            a -= a % floor;
             int r = (rgb >> 16) & 0xff;
-            r -= r % flooring;
+            r -= r % floor;
             int g = (rgb >> 8) & 0xff;
-            g -= g % flooring;
-            int b = (rgb >> 0) & 0xff;
-            b -= b % flooring;
+            g -= g % floor;
+            int b = rgb & 0xff;
+            b -= b % floor;
 
             //put back together
             rgb = ((a & 0xFF) << 24)
                     | ((r & 0xFF) << 16)
                     | ((g & 0xFF) << 8)
-                    | ((b & 0xFF) << 0);
+                    | (b & 0xFF);
         }
 
         if (colorBag.containsKey(rgb)) {
@@ -156,14 +211,26 @@ public static SColor getSColor(int rgb) {
      * @param b
      * @return
      */
-    public static SColor getSColor(int r, int g, int b) {
+    public static SColor asSColor(int r, int g, int b) {
         r = Math.min(r, 255);
         r = Math.max(r, 0);
         g = Math.min(g, 255);
         g = Math.max(g, 0);
         b = Math.min(b, 255);
         b = Math.max(b, 0);
-        return getSColor(r * 256 * 256 + g * 256 + b);
+        return asSColor(r * 256 * 256 + g * 256 + b);
+    }
+
+    /**
+     * Returns an SColor representation of the provided Color. If there is a
+     * named SColor constant that matches the value, then that constant is
+     * returned.
+     *
+     * @param color
+     * @return
+     */
+    public static SColor asSColor(Color color) {
+        return colorForValue(color.getRGB());
     }
 
     /**
@@ -243,7 +310,7 @@ public static SColor desaturated(SColor color) {
         int b = color.getBlue();
         int average = (int) (r * 0.299 + g * 0.587 + b * 0.114);
 
-        return getSColor(average, average, average);
+        return asSColor(average, average, average);
     }
 
     /**
@@ -267,7 +334,7 @@ public static SColor desaturate(SColor color, double percent) {
      * @param color2
      * @return
      */
-    public static ArrayList getGradient(SColor color1, SColor color2) {
+    public static ArrayList asGradient(SColor color1, SColor color2) {
         String name = palletNamer(color1, color2);
         if (pallets.containsKey(name)) {
             return pallets.get(name);
@@ -291,7 +358,7 @@ public static ArrayList getGradient(SColor color1, SColor color2) {
      * @param name
      * @return
      */
-    public static ArrayList getPallet(String name) {
+    public static ArrayList pallet(String name) {
         return pallets.get(name);
     }
 
@@ -307,7 +374,7 @@ public static ArrayList getPallet(String name) {
      * @param percent
      * @return
      */
-    public static SColor getFromPallet(String name, float percent) {
+    public static SColor fromPallet(String name, float percent) {
         ArrayList list = pallets.get(name);
         if (list == null) {
             return null;
@@ -319,6 +386,28 @@ public static SColor getFromPallet(String name, float percent) {
         return list.get(index);
     }
 
+    /**
+     * Returns an SColor chosen from a pop-up JColorChooser dialog.
+     *
+     * @param parent The component which is the parent of this dialog
+     * @return
+     */
+    public static SColor showSColorChooser(Component parent) {
+        final JColorChooser chooser = new JColorChooser();
+        chooser.setChooserPanels(new AbstractColorChooserPanel[]{new SColorChooserPanel()});
+
+        JDialog dialog = JColorChooser.createDialog(parent, "Choose A Color", true, chooser, new ActionListener() {
+            public void actionPerformed(ActionEvent e) {
+                pickedColor = asSColor(chooser.getColor().getRGB());
+            }
+        }, null);
+        dialog.setLocationRelativeTo(parent);
+        dialog.setVisible(true);
+
+        return pickedColor;
+    }
+    private static SColor pickedColor;//needed for the color chooser
+
     /**
      * Places the pallet into the cache, along with each of the member colors.
      *
@@ -330,7 +419,7 @@ public static void addPallet(String name, ArrayList pallet) {
 
         //make sure all the colors in the pallet are also in the general color cache
         for (SColor sc : pallet) {
-            temp.add(getSColor(sc.getRGB()));
+            temp.add(asSColor(sc.getRGB()));
         }
 
         pallets.put(name, temp);
@@ -355,7 +444,7 @@ private static Point3D scolorToCoord3D(SColor color) {
      * @return
      */
     private static SColor coord3DToSColor(Point3D coord) {
-        return getSColor(coord.x, coord.y, coord.z);
+        return asSColor(coord.x, coord.y, coord.z);
     }
 
     private static String palletNamer(SColor color1, SColor color2) {
diff --git a/src/main/java/squidpony/squidgrid/fov/BasicRadiusStrategy.java b/src/main/java/squidpony/squidgrid/fov/BasicRadiusStrategy.java
index 19ff47dda0..2ca001f40e 100644
--- a/src/main/java/squidpony/squidgrid/fov/BasicRadiusStrategy.java
+++ b/src/main/java/squidpony/squidgrid/fov/BasicRadiusStrategy.java
@@ -3,7 +3,7 @@
 /**
  * Basic radius strategy implementations.
  *
- * @author Eben Howard - http://squidpony.com - eben@squidpony.com
+ * @author Eben Howard - http://squidpony.com - howard@squidpony.com
  */
 public enum BasicRadiusStrategy implements RadiusStrategy {
 
diff --git a/src/main/java/squidpony/squidgrid/fov/BresenhamLOS.java b/src/main/java/squidpony/squidgrid/fov/BresenhamLOS.java
index 1f3ebee3b6..773ad9d42d 100644
--- a/src/main/java/squidpony/squidgrid/fov/BresenhamLOS.java
+++ b/src/main/java/squidpony/squidgrid/fov/BresenhamLOS.java
@@ -4,47 +4,43 @@
 import java.util.LinkedList;
 import java.util.Queue;
 import squidpony.squidmath.Bresenham;
-import squidpony.squidmath.Point3D;
 
 /**
  * A Bresenham-based line-of-sight algorithm.
  *
- * @author Eben Howard - http://squidpony.com - eben@squidpony.com
+ * @author Eben Howard - http://squidpony.com - howard@squidpony.com
  */
 public class BresenhamLOS implements LOSSolver {
 
-    Queue lastPath = new LinkedList<>();
+    Queue lastPath = new LinkedList<>();
 
     @Override
-    public boolean isReachable(float[][] map, int x, int y, int targetX, int targetY, float force, float decay, RadiusStrategy radiusStrategy) {
-        Queue path = Bresenham.line2D(x, y, targetX, targetY);
+    public boolean isReachable(float[][] resistanceMap, int startx, int starty, int targetx, int targety, float force, float decay, RadiusStrategy radiusStrategy) {
+        Queue path = Bresenham.line2D(startx, starty, targetx, targety);
         lastPath = new LinkedList<>(path);//save path for later retreival
-        path.poll();//remove starting point
-        for (Point3D p : path) {
-            if (p.x == targetX && p.y == targetY) {
+        float currentForce = force;
+        for (Point p : path) {
+            if (p.x == targetx && p.y == targety) {
                 return true;//reached the end 
             }
-            force -= map[p.x][p.y];
-            double radius = radiusStrategy.radius(x, y, p.x, p.y);
-            if (force - (radius * decay) <= 0) {
+            if (p.x != startx || p.y != starty) {//don't discount the start location even if on resistant cell
+                currentForce *= (1 - resistanceMap[p.x][p.y]);
+            }
+            double radius = radiusStrategy.radius(startx, starty, p.x, p.y);
+            if (currentForce - (radius * decay) <= 0) {
                 return false;//too much resistance
             }
         }
-        return true;//made it all the way to the target
+        return false;//never got to the target point
     }
 
     @Override
     public Queue getLastPath() {
-        //copy the Point3D elements into a 2D Point structure only if needed
-        Queue returnPath = new LinkedList<>();
-        for (Point3D p : lastPath) {
-            returnPath.add(new Point(p.x, p.y));
-        }
-        return returnPath;
+        return lastPath;
     }
 
     @Override
     public boolean isReachable(float[][] resistanceMap, int startx, int starty, int targetx, int targety) {
-        return isReachable(resistanceMap, startx, starty, targety, targety, Float.MAX_VALUE, 0f, BasicRadiusStrategy.CIRCLE);
+        return isReachable(resistanceMap, startx, starty, targetx, targety, Float.MAX_VALUE, 0f, BasicRadiusStrategy.CIRCLE);
     }
 }
diff --git a/src/main/java/squidpony/squidgrid/fov/EliasFOV.java b/src/main/java/squidpony/squidgrid/fov/EliasFOV.java
new file mode 100644
index 0000000000..36bfcd8101
--- /dev/null
+++ b/src/main/java/squidpony/squidgrid/fov/EliasFOV.java
@@ -0,0 +1,90 @@
+package squidpony.squidgrid.fov;
+
+import squidpony.annotation.Beta;
+import squidpony.squidmath.Elias;
+
+/**
+ * Uses the Elias line running to raycast.
+ *
+ * Does not currently support translucency.
+ * 
+ * For information on the sideview parameter, see the EliasLOS documentation.
+ *
+ * @author Eben Howard - http://squidpony.com - howard@squidpony.com
+ */
+@Beta
+public class EliasFOV implements FOVSolver {
+
+    private float[][] lightMap, resistanceMap;
+    private float maxRadius, force, decay;
+    private int width, height;
+    private RadiusStrategy rStrat;
+    private float sideview = 0.75f;
+
+    /**
+     * Creates a solver which will use the default sideview on the internal
+     * EliasLOS solver.
+     */
+    public EliasFOV() {
+    }
+
+    /**
+     * Creates a solver which will use the provided sideview value on the
+     * internal EliasLOS solver.
+     *
+     * @param sideview
+     */
+    public EliasFOV(float sideview) {
+        this.sideview = sideview;
+    }
+
+    @Override
+    public float[][] calculateFOV(float[][] resistanceMap, int startx, int starty, float force, float decay, RadiusStrategy radiusStrategy) {
+        this.resistanceMap = resistanceMap;
+        width = resistanceMap.length;
+        height = resistanceMap[0].length;
+        lightMap = new float[width][height];
+        this.force = force;
+        this.decay = decay;
+        rStrat = radiusStrategy;
+
+        maxRadius = force / decay;
+        int left = (int) Math.max(0, startx - maxRadius - 1);
+        int right = (int) Math.min(width - 1, startx + maxRadius + 1);
+        int top = (int) Math.max(0, starty - maxRadius - 1);
+        int bottom = (int) Math.min(height - 1, starty + maxRadius + 1);
+
+
+        //run rays out to edges
+        for (int x = left; x <= right; x++) {
+            runLineGroup(startx, starty, x, top);
+            runLineGroup(startx, starty, x, bottom);
+        }
+        for (int y = top; y <= bottom; y++) {
+            runLineGroup(startx, starty, left, y);
+            runLineGroup(startx, starty, right, y);
+        }
+
+        return lightMap;
+    }
+
+    private void runLineGroup(int startx, int starty, int endx, int endy) {
+        float[][] tempMap = Elias.lightMap(startx, starty, endx, endy);
+        EliasLOS los = new EliasLOS(sideview);
+//        boolean xpositive = endx > startx;
+//        boolean ypositive = endy > starty;
+        for (int x = Math.min(startx, endx); x <= Math.max(startx, endx); x++) {
+            for (int y = Math.min(starty, endy); y <= Math.max(starty, endy); y++) {
+                float radius = rStrat.radius(startx, starty, x, y);
+                if (radius < maxRadius && los.isReachable(resistanceMap, startx, starty, x, y)) {
+                    lightMap[x][y] = Math.max(lightMap[x][y], tempMap[x][y] * (force - radius * decay));
+                }
+            }
+        }
+    }
+
+    @Override
+    public float[][] calculateFOV(float[][] resistanceMap, int startx, int starty, float radius) {
+        return calculateFOV(resistanceMap, startx, starty, 1, 1 / radius, BasicRadiusStrategy.CIRCLE);
+    }
+}
diff --git a/src/main/java/squidpony/squidgrid/fov/EliasLOS.java b/src/main/java/squidpony/squidgrid/fov/EliasLOS.java
new file mode 100644
index 0000000000..a107e0d20e
--- /dev/null
+++ b/src/main/java/squidpony/squidgrid/fov/EliasLOS.java
@@ -0,0 +1,90 @@
+package squidpony.squidgrid.fov;
+
+import java.awt.Point;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Queue;
+import squidpony.annotation.Beta;
+import squidpony.squidmath.Elias;
+
+/**
+ * Uses Wu's Algorithm as modified by Elias to draw the line.
+ *
+ * The side view parameter is how far along the antialiased path to consider
+ * when determining if the far end can be seen, from 0.0 to 1.0 with 1.0
+ * considering the entire line. The closer to 1.0 this value is, the more
+ * complete and symmetrical end-to-end the line is, but the computation cost
+ * also increases.
+ *
+ * If undesired artifacts are seen when running the lines (missing squares
+ * perhaps), try increasing the sideview value.
+ *
+ * @author Eben Howard - http://squidpony.com - howard@squidpony.com
+ */
+@Beta
+public class EliasLOS implements LOSSolver {
+
+    private Queue lastPath = new LinkedList<>();
+    private float sideview = 0.75f;
+
+    /**
+     * Creates this solver with the default side view parameter.
+     */
+    public EliasLOS() {
+    }
+
+    /**
+     * Creates this solver with the provided value for how far along the
+     * antialiased line the antialiased portion will be considered.
+     *
+     * @param sideview
+     */
+    public EliasLOS(float sideview) {
+        this.sideview = sideview;
+    }
+
+    public float getSideview() {
+        return sideview;
+    }
+
+    public void setSideview(float sideview) {
+        this.sideview = sideview;
+    }
+
+    @Override
+    public boolean isReachable(float[][] resistanceMap, int startx, int starty, int targetx, int targety, float force, float decay, RadiusStrategy radiusStrategy) {
+        List path = Elias.line(startx, starty, targetx, targety);
+        lastPath = new LinkedList<>(path);//save path for later retreival
+
+        BresenhamLOS los1 = new BresenhamLOS(),
+                los2 = new BresenhamLOS();
+
+        float checkRadius = radiusStrategy.radius(startx, starty) * 0.75f;
+        while (!path.isEmpty()) {
+            Point p = path.remove(0);
+
+            //if a non-solid midpoint on the path can see both the start and end, consider the two ends to be able to see each other
+            if (resistanceMap[p.x][p.y] < 1
+                    && radiusStrategy.radius(startx, starty, p.x, p.y) < checkRadius
+                    && los1.isReachable(resistanceMap, p.x, p.y, targetx, targety, force - (radiusStrategy.radius(startx, starty, p.x, p.y) * decay), decay, radiusStrategy)
+                    && los2.isReachable(resistanceMap, startx, starty, p.x, p.y, force, decay, radiusStrategy)) {
+
+                //record actual sight path used
+                lastPath = new LinkedList<>(los1.lastPath);
+                lastPath.addAll(los2.lastPath);
+                return true;
+            }
+        }
+        return false;//never got to the target point
+    }
+
+    @Override
+    public boolean isReachable(float[][] resistanceMap, int startx, int starty, int targetx, int targety) {
+        return isReachable(resistanceMap, startx, starty, targetx, targety, Float.MAX_VALUE, 0f, BasicRadiusStrategy.CIRCLE);
+    }
+
+    @Override
+    public Queue getLastPath() {
+        return lastPath;
+    }
+}
diff --git a/src/main/java/squidpony/squidgrid/fov/FOVSolver.java b/src/main/java/squidpony/squidgrid/fov/FOVSolver.java
index c7312f6fbc..0f608822a5 100644
--- a/src/main/java/squidpony/squidgrid/fov/FOVSolver.java
+++ b/src/main/java/squidpony/squidgrid/fov/FOVSolver.java
@@ -22,7 +22,7 @@
  * are not opaque. Check the documentation for the individual solvers for more
  * details.
  *
- * @author Eben Howard - http://squidpony.com - eben@squidpony.com
+ * @author Eben Howard - http://squidpony.com - howard@squidpony.com
  */
 public interface FOVSolver {
 
diff --git a/src/main/java/squidpony/squidgrid/fov/LOSSolver.java b/src/main/java/squidpony/squidgrid/fov/LOSSolver.java
index e860d0b38a..bfabd9e625 100644
--- a/src/main/java/squidpony/squidgrid/fov/LOSSolver.java
+++ b/src/main/java/squidpony/squidgrid/fov/LOSSolver.java
@@ -14,7 +14,7 @@
  * calculation of force, decay, and resistances prevent the line from reaching
  * the target.
  *
- * @author Eben Howard - http://squidpony.com - eben@squidpony.com
+ * @author Eben Howard - http://squidpony.com - howard@squidpony.com
  */
 public interface LOSSolver {
 
diff --git a/src/main/java/squidpony/squidgrid/fov/MergedFOV.java b/src/main/java/squidpony/squidgrid/fov/MergedFOV.java
index 28024c92d2..aa1070f44d 100644
--- a/src/main/java/squidpony/squidgrid/fov/MergedFOV.java
+++ b/src/main/java/squidpony/squidgrid/fov/MergedFOV.java
@@ -1,13 +1,15 @@
 package squidpony.squidgrid.fov;
 
+import squidpony.annotation.Beta;
+
 /**
  * This class merges the results from two or more FOVSolvers.
  * 
  * Currently a work in progress.
  *
  * @author Eben Howard - http://squidpony.com - howard@squidpony.com
- * @deprecated 
  */
+@Beta
 public class MergedFOV implements FOVSolver {
     
     private float totalWeight;
diff --git a/src/main/java/squidpony/squidgrid/fov/RadiusStrategy.java b/src/main/java/squidpony/squidgrid/fov/RadiusStrategy.java
index 9907e45c6d..8d4a4001e0 100644
--- a/src/main/java/squidpony/squidgrid/fov/RadiusStrategy.java
+++ b/src/main/java/squidpony/squidgrid/fov/RadiusStrategy.java
@@ -4,7 +4,7 @@
  * Indicates which method of dealing with the radius during FOV and LOS solving
  * is preferred.
  *
- * @author Eben Howard - http://squidpony.com - eben@squidpony.com
+ * @author Eben Howard - http://squidpony.com - howard@squidpony.com
  */
 public interface RadiusStrategy {
 
diff --git a/src/main/java/squidpony/squidgrid/fov/RayCastingFOV.java b/src/main/java/squidpony/squidgrid/fov/RayCastingFOV.java
index e4ecd4d6f9..59c641171f 100644
--- a/src/main/java/squidpony/squidgrid/fov/RayCastingFOV.java
+++ b/src/main/java/squidpony/squidgrid/fov/RayCastingFOV.java
@@ -1,5 +1,7 @@
 package squidpony.squidgrid.fov;
 
+import squidpony.annotation.Beta;
+
 /**
  * Simple raytracing algorithm for Field of View. In large areas will be
  * relatively inefficient due to repeated visiting of some cells.
@@ -17,9 +19,9 @@
  * 
  * Currently a work in progress.
  *
- * @deprecated 
- * @author Eben Howard - http://squidpony.com - eben@squidpony.com
+ * @author Eben Howard - http://squidpony.com - howard@squidpony.com
  */
+@Beta
 public class RayCastingFOV implements FOVSolver {
 
     private float gap = 0.4f;//how much gap to leave from the edges when tracing rays
@@ -48,15 +50,15 @@ public RayCastingFOV() {
     }
 
     @Override
-    public float[][] calculateFOV(float[][] map, int startx, int starty, float force, float decay, RadiusStrategy radiusStrategy) {
-        this.map = map;
+    public float[][] calculateFOV(float[][] resistanceMap, int startx, int starty, float force, float decay, RadiusStrategy radiusStrategy) {
+        this.map = resistanceMap;
         this.force = force;
         this.decay = decay;
         this.fx = startx + 0.5f;
         this.fy = starty + 0.5f;
         this.rStrat = radiusStrategy;
-        width = map.length;
-        height = map[0].length;
+        width = resistanceMap.length;
+        height = resistanceMap[0].length;
         lightMap = new float[width][height];
 
         float maxRadius = force / decay + 1;
@@ -142,7 +144,7 @@ private void runLine(float x, float y, double angle, float currentLight) {
     }
 
     @Override
-    public float[][] calculateFOV(float[][] map, int startx, int starty, float radius) {
-        return calculateFOV(map, startx, starty, 1, 1 / radius, BasicRadiusStrategy.CIRCLE);
+    public float[][] calculateFOV(float[][] resistanceMap, int startx, int starty, float radius) {
+        return calculateFOV(resistanceMap, startx, starty, 1, 1 / radius, BasicRadiusStrategy.CIRCLE);
     }
 }
diff --git a/src/main/java/squidpony/squidgrid/fov/RayCastingLOS.java b/src/main/java/squidpony/squidgrid/fov/RayCastingLOS.java
index 45a688a41e..dfdf26eb3d 100644
--- a/src/main/java/squidpony/squidgrid/fov/RayCastingLOS.java
+++ b/src/main/java/squidpony/squidgrid/fov/RayCastingLOS.java
@@ -3,6 +3,7 @@
 import java.awt.Point;
 import java.util.LinkedList;
 import java.util.Queue;
+import squidpony.annotation.Beta;
 
 /**
  * Uses a series of rays internal to the start and end point to determine
@@ -10,6 +11,7 @@
  *
  * @author Eben Howard - http://squidpony.com - howard@squidpony.com
  */
+@Beta
 public class RayCastingLOS implements LOSSolver {
 
     Queue path;
diff --git a/src/main/java/squidpony/squidgrid/fov/RippleFOV.java b/src/main/java/squidpony/squidgrid/fov/RippleFOV.java
index c7d28ffe64..235c95ec5f 100644
--- a/src/main/java/squidpony/squidgrid/fov/RippleFOV.java
+++ b/src/main/java/squidpony/squidgrid/fov/RippleFOV.java
@@ -1,17 +1,21 @@
 package squidpony.squidgrid.fov;
 
+import squidpony.annotation.Beta;
+
 /**
  * Performs FOV by pushing values outwards from the source location. It will
  * only go around corners slightly.
  *
  * This algorithm does perform bounds checking.
  *
- * @author Eben Howard - http://squidpony.com - eben@squidpony.com
+ * @author Eben Howard - http://squidpony.com - howard@squidpony.com
  */
+@Beta
 public class RippleFOV implements FOVSolver {
 
     private float[][] lightMap;
     private float[][] map;
+    private boolean[][] indirect;//marks when a tile is only indirectly lit
     private float radius, decay;
     private int startx, starty, width = 1, height = 1;
     private RadiusStrategy rStrat;
@@ -27,6 +31,14 @@ public RippleFOV() {
      * @return
      */
     private float getNearLight(int x, int y) {
+        if (Math.abs(startx - x) <= 1 && Math.abs(starty - y) <= 1) {//if next to start cell, get full light
+            return lightMap[startx][starty];
+        }
+
+        if (indirect[x][y]) {
+            return 0f;//no light if this one was only indirectly lit
+        }
+
         int x2 = x - (int) Math.signum(x - startx);
         int y2 = y - (int) Math.signum(y - starty);
 
@@ -48,9 +60,8 @@ private float getNearLight(int x, int y) {
 
         //find largest emmitted light in direction of source
         float light = 0f;
-        int close = rStrat.radius(startx, starty, x, y) <= 1 ? 0 : 1; //if next to start cell, don't apply start cell's resistance
-        if (map[x2][y2] < 1f && lightMap[x2][y2] > 0) {
-            light = Math.max(light, lightMap[x2][y2] * (1 - close * map[x2][y2]));
+        if (!indirect[x2][y2] && map[x2][y2] < 1f && lightMap[x2][y2] > 0) {
+            light = Math.max(light, lightMap[x2][y2] * (1 - map[x2][y2]));
             mainLit = true;
         }
 
@@ -58,43 +69,47 @@ private float getNearLight(int x, int y) {
         if (x2 == x) {//add one left and right
             int dx1 = Math.max(0, x - 1);
             int dx2 = Math.min(width - 1, x + 1);
-            int dy = y2;
-            if (map[dx2][dy] < 1f && lightMap[dx2][dy] > 0) {
-                light = Math.max(light, lightMap[dx2][dy] * (1 - close * map[dx2][dy]));
+            int dy = y + (int) Math.signum(y - starty);//move one step further away from the source
+            dy = Math.max(dy, 0);
+            dy = Math.min(dy, height - 1);
+            if (!indirect[dx2][dy] && map[dx2][dy] < 1f && lightMap[dx2][dy] > 0) {
+                light = Math.max(light, lightMap[dx2][dy] * (1 - map[dx2][dy]));
                 sideALit = true;
             }
-            if (map[dx1][dy] < 1f && lightMap[dx1][dy] > 0) {
-                light = Math.max(light, lightMap[dx1][dy] * (1 - close * map[dx1][dy]));
+            if (!indirect[dx1][dy] && map[dx1][dy] < 1f && lightMap[dx1][dy] > 0) {
+                light = Math.max(light, lightMap[dx1][dy] * (1 - map[dx1][dy]));
                 sideBLit = true;
             }
         } else if (y2 == y) {//add one up and one down
             int dy1 = Math.max(0, y - 1);
             int dy2 = Math.min(height - 1, y + 1);
-            int dx = x2;
-            if (map[dx][dy1] < 1f && lightMap[dx][dy1] > 0) {
-                light = Math.max(light, lightMap[dx][dy1] * (1 - close * map[dx][dy1]));
+            int dx = x + (int) Math.signum(x - startx);//move one step further away from the source
+            dx = Math.max(dx, 0);
+            dx = Math.min(dx, width - 1);
+            if (!indirect[dx][dy1] && map[dx][dy1] < 1f && lightMap[dx][dy1] > 0) {
+                light = Math.max(light, lightMap[dx][dy1] * (1 - map[dx][dy1]));
                 sideALit = true;
             }
-            if (map[dx][dy2] < 1f && lightMap[dx][dy2] > 0) {
-                light = Math.max(light, lightMap[dx][dy2] * (1 - close * map[dx][dy2]));
+            if (!indirect[dx][dy2] && map[dx][dy2] < 1f && lightMap[dx][dy2] > 0) {
+                light = Math.max(light, lightMap[dx][dy2] * (1 - map[dx][dy2]));
                 sideBLit = true;
             }
         } else {
-            if (xDominance > 0 && map[x2][y] < 1f && lightMap[x2][y] > 0) {
+            if (!indirect[x2][y] && xDominance > 0 && map[x2][y] < 1f && lightMap[x2][y] > 0) {
                 float tempLight = lightMap[x2][y];
                 if (tempLight > 0) {
-                    light = Math.max(light, tempLight * (1 - close * map[x2][y]));
+                    light = Math.max(light, tempLight * (1 - map[x2][y]));
                     sideALit = true;
                 }
-            } else if (xDominance < 0 && map[x][y2] < 1f && lightMap[x][y2] > 0) {
+            } else if (!indirect[x][y2] && xDominance < 0 && map[x][y2] < 1f && lightMap[x][y2] > 0) {
                 float tempLight = lightMap[x][y2];
                 if (tempLight > 0) {
-                    light = Math.max(light, tempLight * (1 - close * map[x][y2]));
+                    light = Math.max(light, tempLight * (1 - map[x][y2]));
                     sideBLit = true;
                 }
-            } else if (xDominance == 0 && (map[x2][y2] < 1f || (map[x][y2] < 1f && map[x2][y] < 1f))) {//on a diagonal 
-                float tempLight = Math.max(lightMap[x2][y2] * (1 - close * map[x2][y2]),
-                        Math.max(lightMap[x2][y] * (1 - close * map[x2][y]), lightMap[x][y2] * (1 - close * map[x][y2])));
+            } else if (!indirect[x2][y2] && xDominance == 0 && (map[x2][y2] < 1f || (map[x][y2] < 1f && map[x2][y] < 1f))) {//on a diagonal 
+                float tempLight = Math.max(lightMap[x2][y2] * (1 - map[x2][y2]),
+                        Math.max(lightMap[x2][y] * (1 - map[x2][y]), lightMap[x][y2] * (1 - map[x][y2])));
                 if (tempLight > 0) {
                     light = Math.max(light, tempLight);
                     mainLit = true;//really it might be that both sides are lit, but that counts the same
@@ -106,12 +121,15 @@ private float getNearLight(int x, int y) {
         boolean killLight = true;//broken out into steps for debugging
         if (mainLit || (sideALit && sideBLit) || corner) {
             killLight = false;
+            if (!mainLit) {
+                indirect[x][y] = true;
+            }
         }
-        if (killLight) {
+        if (killLight) {//not lit at all counts as indirectly lit
             light = 0;
         }
 
-        light = light - decay * distance;
+        light -= decay * distance;
         return light;
     }
 
@@ -128,10 +146,12 @@ public float[][] calculateFOV(float[][] map, int startx, int starty, float force
             width = map.length;
             height = map[0].length;
             lightMap = new float[width][height];
-        }else{
-            for(int x = 0;x= width || y < 0 || y >= height || shadowMap[x][y] <= 0 || lightMap[x][y] >= light) {
+            return;//out of light, off the edge, base fov not lit, or already well lit
+        }
+
+        lightMap[x][y] = light;//apply passed in light
+
+        if (type == PRIMARY) {
+            //push primary ray
+            float radius = rStrat.radius(x, y, x + dir.deltaX, y + dir.deltaY);
+            float brightness = light;
+            brightness *= (1 - resistanceMap[x][y]);//light is reduced by the portion of the square passed through
+            brightness -= radius * decay;//reduce by the amount of decay from passing through
+            pushLight(x + dir.deltaX, y + dir.deltaY, brightness, dir, dir, PRIMARY);
+
+            Direction pushing = dir.clockwise();
+            radius = rStrat.radius(x, y, x + pushing.deltaX, y + pushing.deltaY);
+            brightness = light * (1 - resistanceMap[x][y]);//light is reduced by the portion of the square passed through
+            brightness -= radius * decay;//reduce by the amount of decay from passing through
+            pushLight(x + pushing.deltaX, y + pushing.deltaY, brightness, dir, pushing, SECONDARY);
+
+            pushing = dir.counterClockwise();
+            radius = rStrat.radius(x, y, x + pushing.deltaX, y + pushing.deltaY);
+            brightness = light * (1 - resistanceMap[x][y]);//light is reduced by the portion of the square passed through
+            brightness -= radius * decay;//reduce by the amount of decay from passing through
+            pushLight(x + pushing.deltaX, y + pushing.deltaY, brightness, dir, pushing, SECONDARY);
+        } else {//type == SECONDARY at this point
+            //push pass-through secondary ray
+            Direction pushing = previous;//redirect to previous' previous direction
+            float radius = rStrat.radius(x, y, x + pushing.deltaX, y + pushing.deltaY);
+            float brightness = light * (1 - resistanceMap[x][y]);//light is reduced by the portion of the square passed through
+            brightness -= radius * decay;//reduce by the amount of decay from passing through
+            pushLight(x + pushing.deltaX, y + pushing.deltaY, brightness, dir, pushing, SECONDARY);
+
+            //now push through tertiary rays, first just continues in direction passed in
+            radius = rStrat.radius(x, y, x + dir.deltaX, y + dir.deltaY);
+            brightness = light * (1 - resistanceMap[x][y]);//light is reduced by the portion of the square passed through
+            brightness -= radius * decay;//reduce by the amount of decay from passing through
+            pushLight(x + dir.deltaX, y + dir.deltaY, brightness, dir, pushing, SECONDARY);
+            if (previous.clockwise().equals(dir)) {
+                pushing = previous.clockwise();
+            } else {
+                pushing = previous.counterClockwise();
+            }
+
+            radius = rStrat.radius(x, y, x + pushing.deltaX, y + pushing.deltaY);
+            brightness = light * (1 - resistanceMap[x][y]);//light is reduced by the portion of the square passed through
+            brightness -= radius * decay;//reduce by the amount of decay from passing through
+            pushLight(x + pushing.deltaX, y + pushing.deltaY, brightness, dir, pushing, SECONDARY);
+        }
+    }
+
+    @Override
+    public float[][] calculateFOV(float[][] resistanceMap, int startx, int starty, float radius) {
+        return calculateFOV(resistanceMap, startx, starty, 1, 1 / radius, BasicRadiusStrategy.CIRCLE);
+    }
+}
diff --git a/src/main/java/squidpony/squidgrid/gui/SGPane.java b/src/main/java/squidpony/squidgrid/gui/SGPane.java
index 0eb41be79a..6b856d86fc 100644
--- a/src/main/java/squidpony/squidgrid/gui/SGPane.java
+++ b/src/main/java/squidpony/squidgrid/gui/SGPane.java
@@ -2,11 +2,18 @@
 
 import java.awt.Color;
 import java.awt.Font;
+import squidpony.annotation.Beta;
 
 /**
+ * A basic interface for working with grids.
  *
- * @author Eben Howard - http://squidpony.com - eben@squidpony.com
+ * This interface's Beta status is due to the libGDX version potentially
+ * becoming different enough that this interface is removed in favor of direct
+ * implementation of desired back end panels.
+ *
+ * @author Eben Howard - http://squidpony.com - howard@squidpony.com
  */
+@Beta
 public interface SGPane {
 
     /**
diff --git a/src/main/java/squidpony/squidgrid/gui/awt/ImageCellMap.java b/src/main/java/squidpony/squidgrid/gui/awt/ImageCellMap.java
index dfb9b56b41..86559a1faf 100644
--- a/src/main/java/squidpony/squidgrid/gui/awt/ImageCellMap.java
+++ b/src/main/java/squidpony/squidgrid/gui/awt/ImageCellMap.java
@@ -11,13 +11,13 @@
 /**
  * Class for managing tile images. All images must be the same dimensions.
  *
- * @author Eben Howard -- http://squidpony.com
+ * @author Eben Howard -- http://squidpony.com - howard@squidpony.com
  */
 public class ImageCellMap implements Map {
 
     private BufferedImage nullImage;
     int cellWidth, cellHeight;
-    TreeMap blocks = new TreeMap();
+    TreeMap blocks = new TreeMap<>();
 
     /**
      * A cached image set.
diff --git a/src/main/java/squidpony/squidgrid/gui/awt/TextCellFactory.java b/src/main/java/squidpony/squidgrid/gui/awt/TextCellFactory.java
index fb0e169644..0ef96636d4 100644
--- a/src/main/java/squidpony/squidgrid/gui/awt/TextCellFactory.java
+++ b/src/main/java/squidpony/squidgrid/gui/awt/TextCellFactory.java
@@ -1,12 +1,14 @@
 package squidpony.squidgrid.gui.awt;
 
 import java.awt.*;
+import java.awt.font.FontRenderContext;
+import java.awt.font.GlyphVector;
 import java.awt.image.BufferedImage;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.TreeMap;
 import squidpony.squidcolor.SColor;
 import squidpony.squidgrid.util.Direction;
-import squidpony.squidutility.Pair;
 
 /**
  * Class for creating text blocks.
@@ -14,7 +16,7 @@
  * The default characters guaranteed to fit are ASCII 33 through 125, which are
  * the commonly used symbols, numbers, and letters.
  *
- * @author Eben Howard - http://squidpony.com
+ * @author Eben Howard - http://squidpony.com - howard@squidpony.com
  */
 public class TextCellFactory implements Cloneable {
 
@@ -181,8 +183,6 @@ private void sizeCellByFont() {
         horizontalOffset = cellWidth / 2;
 
         findSize();
-        cullLargeCharacters();
-        trimCell();
 
         //restore cell sizes based on padding
         leftPadding = tempLeftPadding;
@@ -196,160 +196,64 @@ private void sizeCellByFont() {
     }
 
     private void findSize() {
-        //size up with square cells, it's okay if we oversize since we'll shrink back down
-        int bestw = 1;
-        int besth = 1;
-        ArrayList testingList;
-        if (!largeCharacters.isEmpty()) {
-            testingList = largeCharacters;
-//            largeCharacters = new ArrayList<>();//TODO -- determine if there are any cases where changing font size would change which character is the widest or tallest
-        } else {
-            testingList = new ArrayList<>();
-            for (char c : fitting) {
-                testingList.add(c);
-            }
-        }
-
-        for (char c : testingList) {//try all requested characters
-            int largestw = 1;
-            int largesth = 1;
-            int smallestw = 1000;
-            int smallesth = 1000;
-
-            //size up until part of the font is seen or size is maxed out, in second case don't change the width and heights
-            float factor = 2f;
-            int maxVal = (int) (1000 / factor);
-            BufferedImage image = new BufferedImage(cellWidth, cellHeight, BufferedImage.TYPE_BYTE_GRAY);
-            boolean visible = visible(c, image);
-            while (maxVal > cellWidth && maxVal > cellHeight && !visible) {
-                cellWidth *= factor;
-                cellHeight *= factor;
-                horizontalOffset = cellWidth / 2;
-                image = new BufferedImage(cellWidth, cellHeight, BufferedImage.TYPE_BYTE_GRAY);
-                visible = visible(c, image);
-            }
+        int left = Integer.MAX_VALUE, right = Integer.MIN_VALUE,
+                top = Integer.MAX_VALUE, bottom = Integer.MIN_VALUE;
+        HashMap larges = new HashMap<>();
 
-            //certain at this point that the character is a printing character, find size that works
-            if (visible) {
-                smallestw = Math.min(smallestw, cellWidth);
-                smallesth = Math.min(smallesth, cellHeight);
-                boolean fits = willFit(c);
-
-                //size up until it fits
-                while (maxVal > cellWidth && maxVal > cellHeight && !fits) {
-                    cellWidth *= factor;
-                    cellHeight *= factor;
-                    horizontalOffset = cellWidth / 2;
-                    fits = willFit(c);
-                }
-                if (fits) {//if it doesn't fit than the requested font is too large
-                    largestw = Math.max(largestw, cellWidth);
-                    largesth = Math.max(largesth, cellHeight);
-
-                    //binary search between smallest and largest to find right size
-                    do {
-                        cellWidth = (int) Math.floor((largestw + smallestw) / 2.0);
-                        cellHeight = (int) Math.floor((largesth + smallesth) / 2.0);//make sure to round up
-                        horizontalOffset = cellWidth / 2;
-
-                        fits = willFit(c);
-                        if (fits) {//enough room, size down
-                            largestw = cellWidth;
-                            largesth = cellHeight;
-                        } else {//not enough room, size up by 1 since we know those sizes didn't work
-                            smallestw = cellWidth + 1;
-                            smallesth = cellHeight + 1;
-                        }
-                    } while (smallestw < largestw && smallesth < largesth);//if equal need to size up once
-
-                    cellWidth = smallestw;
-                    cellHeight = smallesth;
-                    horizontalOffset = cellWidth / 2;
-                    bestw = Math.max(bestw, cellWidth);
-                    besth = Math.max(besth, cellHeight);
-
-                    if (bestw == cellWidth || besth == cellHeight) {//this character hit an edge and expanded the cell size requirement, log it
-                        largeCharacters.add(c);
-                    }
-                }
-            } else {
-                cellWidth = largestw;
-                cellHeight = largesth;
-            }
-        }
-
-        cellWidth = bestw;
-        cellHeight = besth;
-        horizontalOffset = cellWidth / 2;
-    }
+        BufferedImage image = new BufferedImage(cellWidth, cellHeight, BufferedImage.TYPE_4BYTE_ABGR);
+        Graphics2D g = image.createGraphics();
+        g.setFont(font);
 
-    private void cullLargeCharacters() {
-        if (largeCharacters.isEmpty()) {
-            return;
+        g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
+        if (antialias) {
+            g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+        } else {
+            g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
         }
 
-        Pair left = new Pair(Integer.MAX_VALUE, ' '),
-                right = new Pair(Integer.MIN_VALUE, ' '),
-                top = new Pair(Integer.MAX_VALUE, ' '),
-                bottom = new Pair(Integer.MIN_VALUE, ' ');
-        BufferedImage image = new BufferedImage(cellWidth, cellHeight, BufferedImage.TYPE_BYTE_GRAY);
-        for (char c : largeCharacters) {
-            BufferedImage tile = makeMonoImage(c, image);
-
-            leftCheck:
-            for (int x = 0; x < Math.min(left.getFirst(), cellWidth); x++) {
-                for (int y = 0; y < cellHeight; y++) {
-                    if (tile.getRGB(x, y) != Color.WHITE.getRGB()) {
-                        left = new Pair(x, c);//this character is further left than any so far so mark it
-                        break leftCheck;
-                    }
+        FontRenderContext context = g.getFontRenderContext();
+
+        for (int i = 0; i < fitting.length; i++) {
+            GlyphVector vect = font.createGlyphVector(context, new char[]{fitting[i]});
+            if (vect.getGlyphCode(0) != font.getMissingGlyphCode()
+                    && !Character.isISOControl(fitting[i])
+                    && !Character.isWhitespace(fitting[i])
+                    && Character.getDirectionality(fitting[i]) == Character.DIRECTIONALITY_LEFT_TO_RIGHT) {
+                Rectangle rect = vect.getGlyphPixelBounds(0, context, 0, 0);
+                if (rect.x < left) {
+                    larges.put(Direction.LEFT, fitting[i]);
+                    left = rect.x;
                 }
-            }
-
-            rightCheck:
-            for (int x = cellWidth - 1; x > Math.max(right.getFirst(), -1); x--) {
-                for (int y = 0; y < cellHeight; y++) {
-                    if (tile.getRGB(x, y) != Color.WHITE.getRGB()) {
-                        right = new Pair(x, c);//this character is further left than any so far so mark it
-                        break rightCheck;
-                    }
+                if (rect.y < top) {
+                    larges.put(Direction.UP, fitting[i]);
+                    top = rect.y;
                 }
-            }
-
-            topCheck:
-            for (int y = 0; y < Math.min(top.getFirst(), cellHeight); y++) {
-                for (int x = 0; x < cellWidth; x++) {
-                    if (tile.getRGB(x, y) != Color.WHITE.getRGB()) {
-                        top = new Pair(y, c);//this character is further left than any so far so mark it
-                        break topCheck;
-                    }
+                if (rect.x + rect.width > right) {
+                    larges.put(Direction.RIGHT, fitting[i]);
+                    right = rect.x + rect.width;
                 }
-            }
-
-            bottomCheck:
-            for (int y = cellHeight - 1; y > Math.max(bottom.getFirst(), -1); y--) {
-                for (int x = 0; x < cellWidth; x++) {
-                    if (tile.getRGB(x, y) != Color.WHITE.getRGB()) {
-                        bottom = new Pair(y, c);//this character is further left than any so far so mark it
-                        break bottomCheck;
-                    }
+                if (rect.y + rect.height > bottom) {
+                    larges.put(Direction.DOWN, fitting[i]);
+                    bottom = rect.y + rect.height;
                 }
             }
-
         }
+        largeCharacters = new ArrayList<>(larges.values());
 
-        largeCharacters = new ArrayList<>();
-        largeCharacters.add(left.getSecond());
-        largeCharacters.add(right.getSecond());
-        largeCharacters.add(top.getSecond());
-        largeCharacters.add(bottom.getSecond());
+        cellWidth = right - left;
+        cellWidth *= 2;
+        cellHeight = bottom - top;
+        cellHeight *= 2;
+        horizontalOffset = cellWidth / 2;
+        verticalOffset = 0;
+        trimCell();
     }
 
     private void trimCell() {
         BufferedImage image = new BufferedImage(cellWidth, cellHeight, BufferedImage.TYPE_BYTE_GRAY);
 
         //find best horizontal offset
-        int bestHorizontalOffset = 0;//worst case, already in position
+        int bestHorizontalOffset = Integer.MIN_VALUE;
         for (char c : largeCharacters) {
             int tempHorizontalOffset = horizontalOffset;
             if (visible(c, image)) {//only calculate on printable characters
@@ -363,7 +267,7 @@ private void trimCell() {
         horizontalOffset = bestHorizontalOffset;
 
         //find best vertical offset
-        int bestVerticalOffset = -cellHeight;//worst case, already in position
+        int bestVerticalOffset = Integer.MIN_VALUE;
         for (char c : largeCharacters) {
             int tempVerticalOffset = verticalOffset;
             while (verticalOffset > -cellHeight && willFit(c)) {
diff --git a/src/main/java/squidpony/squidgrid/gui/awt/event/SGKeyListener.java b/src/main/java/squidpony/squidgrid/gui/awt/event/SGKeyListener.java
index 316532e2d3..e219df34bc 100644
--- a/src/main/java/squidpony/squidgrid/gui/awt/event/SGKeyListener.java
+++ b/src/main/java/squidpony/squidgrid/gui/awt/event/SGKeyListener.java
@@ -18,7 +18,7 @@
  * regularly checks for user input. If your application is event driven then a
  * standard java.awt.even.KeyListener would be more appropriate to use;
  *
- * @author Eben Howard - http://squidpony.com - eben@squidpony.com
+ * @author Eben Howard - http://squidpony.com - howard@squidpony.com
  */
 public class SGKeyListener implements KeyListener, Iterable, Iterator {
 
diff --git a/src/main/java/squidpony/squidgrid/gui/awt/event/SGMouseListener.java b/src/main/java/squidpony/squidgrid/gui/awt/event/SGMouseListener.java
index 675867ae2b..52b41b7761 100644
--- a/src/main/java/squidpony/squidgrid/gui/awt/event/SGMouseListener.java
+++ b/src/main/java/squidpony/squidgrid/gui/awt/event/SGMouseListener.java
@@ -11,7 +11,7 @@
  * This class is meant to be used as a wrapper to your own mouse listener, it
  * simply converts the coordinates from UI Component x,y to Grid based x,y
  *
- * @author Eben Howard - http://squidpony.com - eben@squidpony.com
+ * @author Eben Howard - http://squidpony.com - howard@squidpony.com
  */
 public class SGMouseListener implements MouseInputListener {
 
diff --git a/src/main/java/squidpony/squidgrid/gui/libgdx/PixmapFactory.java b/src/main/java/squidpony/squidgrid/gui/libgdx/PixmapFactory.java
deleted file mode 100644
index 42e5771884..0000000000
--- a/src/main/java/squidpony/squidgrid/gui/libgdx/PixmapFactory.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package squidpony.squidgrid.gui.libgdx;
-
-import com.badlogic.gdx.graphics.Pixmap;
-import java.awt.image.BufferedImage;
-
-/**
- * Provides methods for converting images to Pixmaps
- *
- * @author Eben Howard - http://squidpony.com - eben@squidpony.com
- */
-public class PixmapFactory {
-
-    /**
-     * Builds and returns a Pixmap based on the input image.
-     *
-     * @param image
-     * @return
-     */
-    public static Pixmap createPixmap(BufferedImage image) {
-        int width = image.getWidth();
-        int height = image.getHeight();
-        Pixmap pix = new Pixmap(width, height, Pixmap.Format.RGBA8888);
-        int[] pixels = image.getRGB(0, 0, width, height, null, 0, width);
-
-        for (int x = 0; x < width; x++) {
-            for (int y = 0; y < height; y++) {
-                int pixel = pixels[y * width + x];
-                pix.drawPixel(x, y, getRGBA(pixel));
-            }
-        }
-
-        return pix;
-    }
-
-    /**
-     * Shifts java.awt.Color ARGB values to gdx RGBA values.
-     *
-     * @param rgb
-     * @return
-     */
-    public static int getRGBA(int rgb) {
-        int a = rgb >> 24;
-        a &= 0x000000ff;
-        int rest = rgb & 0x00ffffff;//mask out the alpha channel
-        rest <<= 8;
-        rest |= a;
-        return rest;
-    }
-}
diff --git a/src/main/java/squidpony/squidgrid/gui/libgdx/SGPanelGDX.java b/src/main/java/squidpony/squidgrid/gui/libgdx/SGPanelGDX.java
deleted file mode 100644
index 643a955dee..0000000000
--- a/src/main/java/squidpony/squidgrid/gui/libgdx/SGPanelGDX.java
+++ /dev/null
@@ -1,286 +0,0 @@
-package squidpony.squidgrid.gui.libgdx;
-
-import com.badlogic.gdx.graphics.Pixmap;
-import com.badlogic.gdx.graphics.Texture;
-import com.badlogic.gdx.scenes.scene2d.Group;
-import com.badlogic.gdx.scenes.scene2d.ui.Image;
-import java.awt.Color;
-import java.awt.Font;
-import java.awt.image.BufferedImage;
-import java.util.TreeMap;
-import squidpony.squidcolor.SColor;
-import squidpony.squidgrid.gui.SGPane;
-import squidpony.squidgrid.gui.awt.TextCellFactory;
-import sun.reflect.generics.reflectiveObjects.NotImplementedException;
-
-/**
- * A libGDX implementation of SPanel that allows both text and graphics.
- *
- * @author Eben Howard - http://squidpony.com - eben@squidpony.com
- */
-public class SGPanelGDX extends Group implements SGPane {
-
-    private TextCellFactory textFactory = new TextCellFactory();
-    private TreeMap imageMap = new TreeMap<>();
-    private Pixmap backgroundImage, foregroundImage;
-    private Image backImage, foreImage;
-    private int cellWidth, cellHeight, gridWidth, gridHeight;
-    private boolean[][] imageChanged;
-    private Font font;
-    private Color defaultBackColor = SColor.BLACK;
-    private Color defaultForeColor = SColor.WHITE;
-
-    @Override
-    public int getCellHeight() {
-        return cellHeight;
-    }
-
-    @Override
-    public int getCellWidth() {
-        return cellWidth;
-    }
-
-    @Override
-    public int getGridHeight() {
-        return gridHeight;
-    }
-
-    @Override
-    public int getGridWidth() {
-        return gridWidth;
-    }
-
-    @Override
-    public void initialize(int cellWidth, int cellHeight, int gridWidth, int gridHeight, Font font) {
-        textFactory.initializeBySize(cellWidth, cellHeight, font);
-        this.font = textFactory.getFont();
-        doInitialization(gridWidth, gridHeight);
-    }
-
-    @Override
-    public void initialize(int gridWidth, int gridHeight, Font font) {
-        textFactory.initializeByFont(font);
-        this.font = textFactory.getFont();
-        doInitialization(gridWidth, gridHeight);
-    }
-
-    /**
-     * Clears backing arrays and sets fields to proper size for the new grid
-     * size.
-     */
-    private void doInitialization(int gridWidth, int gridHeight) {
-        this.gridWidth = gridWidth;
-        this.gridHeight = gridHeight;
-
-        imageChanged = new boolean[gridWidth][gridHeight];
-        for (int x = 0; x < gridWidth; x++) {
-            for (int y = 0; y < gridHeight; y++) {
-                imageChanged[x][y] = true;
-            }
-        }
-
-        cellWidth = textFactory.getCellDimension().width;
-        cellHeight = textFactory.getCellDimension().height;
-
-        int w = gridWidth * cellWidth;
-        int h = gridHeight * cellHeight;
-        this.setWidth(w);
-        this.setHeight(h);
-        this.setOrigin(0, 0);
-        this.setPosition(0, 0);
-        backgroundImage = new Pixmap(w, h, Pixmap.Format.RGBA8888);
-        foregroundImage = new Pixmap(w, h, Pixmap.Format.RGBA8888);
-        backImage = new Image();
-        foreImage = new Image();
-        refresh();
-    }
-
-    @Override
-    public void clearCell(int x, int y) {
-        placeCharacter(x, y, ' ', defaultBackColor, defaultBackColor);
-    }
-
-    @Override
-    public void clearCell(int x, int y, Color color) {
-        placeCharacter(x, y, ' ', color, color);
-    }
-
-    @Override
-    public void setCellBackground(int x, int y, Color color) {
-        throw new NotImplementedException();
-    }
-
-    @Override
-    public void placeCharacter(int x, int y, char c) {
-        placeCharacter(x, y, c, defaultForeColor, defaultBackColor);
-    }
-
-    @Override
-    public void placeCharacter(int x, int y, char c, Color fore, Color back) {
-        String key = textFactory.getStringRepresentationOf(' ', back, back);
-        Pixmap background = imageMap.get(key);
-        if (background == null) {
-            background = PixmapFactory.createPixmap(textFactory.getImageFor(' ', back, back));
-            imageMap.put(key, background);
-        }
-        placeImage(x, y, background, false);
-
-        if (c != ' ') {
-            key = textFactory.getStringRepresentationOf(c, fore, back);
-            Pixmap image = imageMap.get(key);
-            if (image == null) {
-                image = PixmapFactory.createPixmap(textFactory.getImageFor(c, fore, back));
-                imageMap.put(key, image);
-            }
-            placeImage(x, y, image, true);
-        }
-    }
-
-    @Override
-    public void placeCharacter(int x, int y, char c, Color fore) {
-        placeCharacter(x, y, c, fore, null);
-    }
-
-    @Override
-    public void placeImage(int x, int y, String key) {
-        Pixmap image = imageMap.get(key);
-        if (image != null) {
-            placeImage(x, y, image, true);
-            imageChanged[x][y] = true;
-        }
-    }
-
-    @Override
-    public void placeImage(int x, int y, String key, Color background) {
-        clearCell(x, y, background);
-
-        Pixmap image = imageMap.get(key);
-        if (image != null) {
-            placeImage(x, y, image, true);
-        }
-        imageChanged[x][y] = true;
-    }
-
-    /**
-     * Places an image at the given grid coordinate.
-     *
-     * @param x
-     * @param y
-     * @param image
-     * @param foreground if true then the image will be placed in the foreground
-     */
-    public void placeImage(int x, int y, Pixmap image, boolean foreground) {
-        imageChanged[x][y] = true;
-        if (foreground) {
-            foregroundImage.drawPixmap(image, getImageX(x), getImageY(y));
-        } else {
-            backgroundImage.drawPixmap(image, getImageX(x), getImageY(y));
-        }
-    }
-
-    @Override
-    public void placeText(int xOffset, int yOffset, char[][] chars) {
-        placeText(xOffset, yOffset, chars, defaultForeColor, defaultBackColor);
-    }
-
-    @Override
-    public void placeText(int xOffset, int yOffset, char[][] chars, Color foreground, Color background) {
-        for (int x = xOffset; x < xOffset + chars.length; x++) {
-            for (int y = yOffset; y < yOffset + chars[0].length; y++) {
-                if (x >= 0 && y >= 0 && x < gridWidth && y < gridHeight) {//check for valid input
-                    if (background != null) {
-                        placeCharacter(x, y, chars[x - xOffset][y - yOffset], foreground, background);
-                    } else {
-                        placeCharacter(x, y, chars[x - xOffset][y - yOffset], foreground);
-                    }
-                }
-            }
-        }
-    }
-
-    @Override
-    public void placeHorizontalString(int xOffset, int yOffset, String string) {
-        placeHorizontalString(xOffset, yOffset, string, defaultForeColor, defaultBackColor);
-    }
-
-    @Override
-    public void placeHorizontalString(int xOffset, int yOffset, String string, Color foreground, Color background) {
-        char[][] temp = new char[string.length()][1];
-        for (int i = 0; i < string.length(); i++) {
-            temp[i][0] = string.charAt(i);
-        }
-        placeText(xOffset, yOffset, temp, foreground, background);
-    }
-
-    @Override
-    public void placeVerticalString(int xOffset, int yOffset, String string, Color foreground, Color background) {
-        placeText(xOffset, yOffset, new char[][]{string.toCharArray()}, foreground, background);
-    }
-
-    @Override
-    public void placeVerticalString(int xOffset, int yOffset, String string) {
-        placeVerticalString(xOffset, yOffset, string, defaultForeColor, defaultBackColor);
-    }
-
-    @Override
-    public void refresh() {
-        removeActor(backImage);
-        removeActor(foreImage);
-        backImage = new Image(new Texture(backgroundImage));
-        foreImage = new Image(new Texture(foregroundImage));
-        backImage.setOrigin(0, 0);
-        foreImage.setOrigin(0, 0);
-        backImage.setPosition(0, 0);
-        foreImage.setPosition(0, 0);
-        addActor(backImage);
-        addActor(foreImage);
-    }
-
-    @Override
-    public void setDefaultBackground(Color defaultBackground) {
-        this.defaultBackColor = defaultBackground;
-    }
-
-    @Override
-    public void setDefaultForeground(Color defaultForeground) {
-        this.defaultForeColor = defaultForeground;
-    }
-
-    @Override
-    public void setText(char[][] chars) {
-        placeText(0, 0, chars);
-    }
-
-    @Override
-    public boolean willFit(char character) {
-        return textFactory.willFit(character);
-    }
-
-    /**
-     * Returns the x value of the cell containing the image point passed in.
-     *
-     * @param x
-     * @return
-     */
-    private int getGridX(int x) {
-        return cellWidth / x;
-    }
-
-    /**
-     * Returns the y value of the cell containing the image point passed in.
-     *
-     * @param y
-     * @return
-     */
-    private int getGridY(int y) {
-        return cellHeight / y;
-    }
-
-    private int getImageX(int x) {
-        return x * cellWidth;
-    }
-
-    private int getImageY(int y) {
-        return y * cellHeight;
-    }
-}
diff --git a/src/main/java/squidpony/squidgrid/gui/swing/JRotation.java b/src/main/java/squidpony/squidgrid/gui/swing/JRotation.java
index fb0d7831ff..b1a5cb864b 100644
--- a/src/main/java/squidpony/squidgrid/gui/swing/JRotation.java
+++ b/src/main/java/squidpony/squidgrid/gui/swing/JRotation.java
@@ -13,9 +13,7 @@
 import javax.swing.JPanel;
 
 /**
- * A rotation selection widget.
- *
- * Based on code by Savvas Dalkitsis on stackoverflow.com
+ * A rotation selection widget for use in Swing applications.
  *
  * @author Eben Howard - http://squidpony.com - howard@squidpony.com
  */
diff --git a/src/main/java/squidpony/squidgrid/gui/swing/SwingPane.java b/src/main/java/squidpony/squidgrid/gui/swing/SwingPane.java
index f1857cd57d..ee7114113e 100644
--- a/src/main/java/squidpony/squidgrid/gui/swing/SwingPane.java
+++ b/src/main/java/squidpony/squidgrid/gui/swing/SwingPane.java
@@ -23,7 +23,7 @@
  * When text is placed, the background color is set separately from the
  * foreground character. When moved, only the foreground character is moved.
  *
- * @author Eben Howard - http://squidpony.com
+ * @author Eben Howard - http://squidpony.com - howard@squidpony.com
  */
 public class SwingPane extends JLayeredPane implements SGPane {
 
diff --git a/src/main/java/squidpony/squidgrid/gui/swing/SwingPaneBeanInfo.java b/src/main/java/squidpony/squidgrid/gui/swing/SwingPaneBeanInfo.java
deleted file mode 100644
index de175b7212..0000000000
--- a/src/main/java/squidpony/squidgrid/gui/swing/SwingPaneBeanInfo.java
+++ /dev/null
@@ -1,1032 +0,0 @@
-package squidpony.squidgrid.gui.swing;
-
-import java.beans.*;
-
-/**
- * The information class for the Swing implementation of SGPane.
- *
- * @author Eben Howard - http://squidpony.com - howard@squidpony.com
- */
-public class SwingPaneBeanInfo extends SimpleBeanInfo {
-
-    // Bean descriptor//GEN-FIRST:BeanDescriptor
-    /*lazy BeanDescriptor*/
-    private static BeanDescriptor getBdescriptor(){
-        BeanDescriptor beanDescriptor = new BeanDescriptor  ( squidpony.squidgrid.gui.swing.SwingPane.class , null ); // NOI18N//GEN-HEADEREND:BeanDescriptor
-
-        // Here you can add code for customizing the BeanDescriptor.
-
-        return beanDescriptor;     }//GEN-LAST:BeanDescriptor
-    // Property identifiers//GEN-FIRST:Properties
-    private static final int PROPERTY_accessibleContext = 0;
-    private static final int PROPERTY_actionMap = 1;
-    private static final int PROPERTY_alignmentX = 2;
-    private static final int PROPERTY_alignmentY = 3;
-    private static final int PROPERTY_ancestorListeners = 4;
-    private static final int PROPERTY_autoscrolls = 5;
-    private static final int PROPERTY_background = 6;
-    private static final int PROPERTY_backgroundSet = 7;
-    private static final int PROPERTY_baselineResizeBehavior = 8;
-    private static final int PROPERTY_border = 9;
-    private static final int PROPERTY_bounds = 10;
-    private static final int PROPERTY_cellDimension = 11;
-    private static final int PROPERTY_cellHeight = 12;
-    private static final int PROPERTY_cellWidth = 13;
-    private static final int PROPERTY_colorModel = 14;
-    private static final int PROPERTY_component = 15;
-    private static final int PROPERTY_componentCount = 16;
-    private static final int PROPERTY_componentCountInLayer = 17;
-    private static final int PROPERTY_componentListeners = 18;
-    private static final int PROPERTY_componentOrientation = 19;
-    private static final int PROPERTY_componentPopupMenu = 20;
-    private static final int PROPERTY_components = 21;
-    private static final int PROPERTY_componentsInLayer = 22;
-    private static final int PROPERTY_containerListeners = 23;
-    private static final int PROPERTY_cursor = 24;
-    private static final int PROPERTY_cursorSet = 25;
-    private static final int PROPERTY_debugGraphicsOptions = 26;
-    private static final int PROPERTY_defaultBackground = 27;
-    private static final int PROPERTY_defaultForeground = 28;
-    private static final int PROPERTY_displayable = 29;
-    private static final int PROPERTY_doubleBuffered = 30;
-    private static final int PROPERTY_dropTarget = 31;
-    private static final int PROPERTY_enabled = 32;
-    private static final int PROPERTY_focusable = 33;
-    private static final int PROPERTY_focusCycleRoot = 34;
-    private static final int PROPERTY_focusCycleRootAncestor = 35;
-    private static final int PROPERTY_focusListeners = 36;
-    private static final int PROPERTY_focusOwner = 37;
-    private static final int PROPERTY_focusTraversable = 38;
-    private static final int PROPERTY_focusTraversalKeys = 39;
-    private static final int PROPERTY_focusTraversalKeysEnabled = 40;
-    private static final int PROPERTY_focusTraversalPolicy = 41;
-    private static final int PROPERTY_focusTraversalPolicyProvider = 42;
-    private static final int PROPERTY_focusTraversalPolicySet = 43;
-    private static final int PROPERTY_font = 44;
-    private static final int PROPERTY_fontSet = 45;
-    private static final int PROPERTY_foreground = 46;
-    private static final int PROPERTY_foregroundSet = 47;
-    private static final int PROPERTY_graphics = 48;
-    private static final int PROPERTY_graphicsConfiguration = 49;
-    private static final int PROPERTY_gridHeight = 50;
-    private static final int PROPERTY_gridWidth = 51;
-    private static final int PROPERTY_height = 52;
-    private static final int PROPERTY_hierarchyBoundsListeners = 53;
-    private static final int PROPERTY_hierarchyListeners = 54;
-    private static final int PROPERTY_ignoreRepaint = 55;
-    private static final int PROPERTY_imageCellMap = 56;
-    private static final int PROPERTY_inheritsPopupMenu = 57;
-    private static final int PROPERTY_inputContext = 58;
-    private static final int PROPERTY_inputMap = 59;
-    private static final int PROPERTY_inputMethodListeners = 60;
-    private static final int PROPERTY_inputMethodRequests = 61;
-    private static final int PROPERTY_inputVerifier = 62;
-    private static final int PROPERTY_insets = 63;
-    private static final int PROPERTY_keyListeners = 64;
-    private static final int PROPERTY_layout = 65;
-    private static final int PROPERTY_lightweight = 66;
-    private static final int PROPERTY_locale = 67;
-    private static final int PROPERTY_location = 68;
-    private static final int PROPERTY_locationOnScreen = 69;
-    private static final int PROPERTY_managingFocus = 70;
-    private static final int PROPERTY_maximumSize = 71;
-    private static final int PROPERTY_maximumSizeSet = 72;
-    private static final int PROPERTY_minimumSize = 73;
-    private static final int PROPERTY_minimumSizeSet = 74;
-    private static final int PROPERTY_mouseListeners = 75;
-    private static final int PROPERTY_mouseMotionListeners = 76;
-    private static final int PROPERTY_mousePosition = 77;
-    private static final int PROPERTY_mouseWheelListeners = 78;
-    private static final int PROPERTY_name = 79;
-    private static final int PROPERTY_nextFocusableComponent = 80;
-    private static final int PROPERTY_opaque = 81;
-    private static final int PROPERTY_optimizedDrawingEnabled = 82;
-    private static final int PROPERTY_paintingForPrint = 83;
-    private static final int PROPERTY_paintingTile = 84;
-    private static final int PROPERTY_parent = 85;
-    private static final int PROPERTY_peer = 86;
-    private static final int PROPERTY_preferredSize = 87;
-    private static final int PROPERTY_preferredSizeSet = 88;
-    private static final int PROPERTY_propertyChangeListeners = 89;
-    private static final int PROPERTY_registeredKeyStrokes = 90;
-    private static final int PROPERTY_requestFocusEnabled = 91;
-    private static final int PROPERTY_rootPane = 92;
-    private static final int PROPERTY_showing = 93;
-    private static final int PROPERTY_size = 94;
-    private static final int PROPERTY_text = 95;
-    private static final int PROPERTY_textCellFactory = 96;
-    private static final int PROPERTY_textFactory = 97;
-    private static final int PROPERTY_toolkit = 98;
-    private static final int PROPERTY_toolTipText = 99;
-    private static final int PROPERTY_topLevelAncestor = 100;
-    private static final int PROPERTY_transferHandler = 101;
-    private static final int PROPERTY_treeLock = 102;
-    private static final int PROPERTY_UIClassID = 103;
-    private static final int PROPERTY_valid = 104;
-    private static final int PROPERTY_validateRoot = 105;
-    private static final int PROPERTY_verifyInputWhenFocusTarget = 106;
-    private static final int PROPERTY_vetoableChangeListeners = 107;
-    private static final int PROPERTY_visible = 108;
-    private static final int PROPERTY_visibleRect = 109;
-    private static final int PROPERTY_width = 110;
-    private static final int PROPERTY_x = 111;
-    private static final int PROPERTY_y = 112;
-
-    // Property array 
-    /*lazy PropertyDescriptor*/
-    private static PropertyDescriptor[] getPdescriptor(){
-        PropertyDescriptor[] properties = new PropertyDescriptor[113];
-    
-        try {
-            properties[PROPERTY_accessibleContext] = new PropertyDescriptor ( "accessibleContext", squidpony.squidgrid.gui.swing.SwingPane.class, "getAccessibleContext", null ); // NOI18N
-            properties[PROPERTY_actionMap] = new PropertyDescriptor ( "actionMap", squidpony.squidgrid.gui.swing.SwingPane.class, "getActionMap", "setActionMap" ); // NOI18N
-            properties[PROPERTY_alignmentX] = new PropertyDescriptor ( "alignmentX", squidpony.squidgrid.gui.swing.SwingPane.class, "getAlignmentX", "setAlignmentX" ); // NOI18N
-            properties[PROPERTY_alignmentY] = new PropertyDescriptor ( "alignmentY", squidpony.squidgrid.gui.swing.SwingPane.class, "getAlignmentY", "setAlignmentY" ); // NOI18N
-            properties[PROPERTY_ancestorListeners] = new PropertyDescriptor ( "ancestorListeners", squidpony.squidgrid.gui.swing.SwingPane.class, "getAncestorListeners", null ); // NOI18N
-            properties[PROPERTY_autoscrolls] = new PropertyDescriptor ( "autoscrolls", squidpony.squidgrid.gui.swing.SwingPane.class, "getAutoscrolls", "setAutoscrolls" ); // NOI18N
-            properties[PROPERTY_background] = new PropertyDescriptor ( "background", squidpony.squidgrid.gui.swing.SwingPane.class, "getBackground", "setBackground" ); // NOI18N
-            properties[PROPERTY_backgroundSet] = new PropertyDescriptor ( "backgroundSet", squidpony.squidgrid.gui.swing.SwingPane.class, "isBackgroundSet", null ); // NOI18N
-            properties[PROPERTY_baselineResizeBehavior] = new PropertyDescriptor ( "baselineResizeBehavior", squidpony.squidgrid.gui.swing.SwingPane.class, "getBaselineResizeBehavior", null ); // NOI18N
-            properties[PROPERTY_border] = new PropertyDescriptor ( "border", squidpony.squidgrid.gui.swing.SwingPane.class, "getBorder", "setBorder" ); // NOI18N
-            properties[PROPERTY_bounds] = new PropertyDescriptor ( "bounds", squidpony.squidgrid.gui.swing.SwingPane.class, "getBounds", "setBounds" ); // NOI18N
-            properties[PROPERTY_cellDimension] = new PropertyDescriptor ( "cellDimension", squidpony.squidgrid.gui.swing.SwingPane.class, "getCellDimension", null ); // NOI18N
-            properties[PROPERTY_cellHeight] = new PropertyDescriptor ( "cellHeight", squidpony.squidgrid.gui.swing.SwingPane.class, "getCellHeight", null ); // NOI18N
-            properties[PROPERTY_cellWidth] = new PropertyDescriptor ( "cellWidth", squidpony.squidgrid.gui.swing.SwingPane.class, "getCellWidth", null ); // NOI18N
-            properties[PROPERTY_colorModel] = new PropertyDescriptor ( "colorModel", squidpony.squidgrid.gui.swing.SwingPane.class, "getColorModel", null ); // NOI18N
-            properties[PROPERTY_component] = new IndexedPropertyDescriptor ( "component", squidpony.squidgrid.gui.swing.SwingPane.class, null, null, "getComponent", null ); // NOI18N
-            properties[PROPERTY_componentCount] = new PropertyDescriptor ( "componentCount", squidpony.squidgrid.gui.swing.SwingPane.class, "getComponentCount", null ); // NOI18N
-            properties[PROPERTY_componentCountInLayer] = new IndexedPropertyDescriptor ( "componentCountInLayer", squidpony.squidgrid.gui.swing.SwingPane.class, null, null, "getComponentCountInLayer", null ); // NOI18N
-            properties[PROPERTY_componentListeners] = new PropertyDescriptor ( "componentListeners", squidpony.squidgrid.gui.swing.SwingPane.class, "getComponentListeners", null ); // NOI18N
-            properties[PROPERTY_componentOrientation] = new PropertyDescriptor ( "componentOrientation", squidpony.squidgrid.gui.swing.SwingPane.class, "getComponentOrientation", "setComponentOrientation" ); // NOI18N
-            properties[PROPERTY_componentPopupMenu] = new PropertyDescriptor ( "componentPopupMenu", squidpony.squidgrid.gui.swing.SwingPane.class, "getComponentPopupMenu", "setComponentPopupMenu" ); // NOI18N
-            properties[PROPERTY_components] = new PropertyDescriptor ( "components", squidpony.squidgrid.gui.swing.SwingPane.class, "getComponents", null ); // NOI18N
-            properties[PROPERTY_componentsInLayer] = new IndexedPropertyDescriptor ( "componentsInLayer", squidpony.squidgrid.gui.swing.SwingPane.class, null, null, "getComponentsInLayer", null ); // NOI18N
-            properties[PROPERTY_containerListeners] = new PropertyDescriptor ( "containerListeners", squidpony.squidgrid.gui.swing.SwingPane.class, "getContainerListeners", null ); // NOI18N
-            properties[PROPERTY_cursor] = new PropertyDescriptor ( "cursor", squidpony.squidgrid.gui.swing.SwingPane.class, "getCursor", "setCursor" ); // NOI18N
-            properties[PROPERTY_cursorSet] = new PropertyDescriptor ( "cursorSet", squidpony.squidgrid.gui.swing.SwingPane.class, "isCursorSet", null ); // NOI18N
-            properties[PROPERTY_debugGraphicsOptions] = new PropertyDescriptor ( "debugGraphicsOptions", squidpony.squidgrid.gui.swing.SwingPane.class, "getDebugGraphicsOptions", "setDebugGraphicsOptions" ); // NOI18N
-            properties[PROPERTY_defaultBackground] = new PropertyDescriptor ( "defaultBackground", squidpony.squidgrid.gui.swing.SwingPane.class, null, "setDefaultBackground" ); // NOI18N
-            properties[PROPERTY_defaultForeground] = new PropertyDescriptor ( "defaultForeground", squidpony.squidgrid.gui.swing.SwingPane.class, null, "setDefaultForeground" ); // NOI18N
-            properties[PROPERTY_displayable] = new PropertyDescriptor ( "displayable", squidpony.squidgrid.gui.swing.SwingPane.class, "isDisplayable", null ); // NOI18N
-            properties[PROPERTY_doubleBuffered] = new PropertyDescriptor ( "doubleBuffered", squidpony.squidgrid.gui.swing.SwingPane.class, "isDoubleBuffered", "setDoubleBuffered" ); // NOI18N
-            properties[PROPERTY_dropTarget] = new PropertyDescriptor ( "dropTarget", squidpony.squidgrid.gui.swing.SwingPane.class, "getDropTarget", "setDropTarget" ); // NOI18N
-            properties[PROPERTY_enabled] = new PropertyDescriptor ( "enabled", squidpony.squidgrid.gui.swing.SwingPane.class, "isEnabled", "setEnabled" ); // NOI18N
-            properties[PROPERTY_focusable] = new PropertyDescriptor ( "focusable", squidpony.squidgrid.gui.swing.SwingPane.class, "isFocusable", "setFocusable" ); // NOI18N
-            properties[PROPERTY_focusCycleRoot] = new PropertyDescriptor ( "focusCycleRoot", squidpony.squidgrid.gui.swing.SwingPane.class, "isFocusCycleRoot", "setFocusCycleRoot" ); // NOI18N
-            properties[PROPERTY_focusCycleRootAncestor] = new PropertyDescriptor ( "focusCycleRootAncestor", squidpony.squidgrid.gui.swing.SwingPane.class, "getFocusCycleRootAncestor", null ); // NOI18N
-            properties[PROPERTY_focusListeners] = new PropertyDescriptor ( "focusListeners", squidpony.squidgrid.gui.swing.SwingPane.class, "getFocusListeners", null ); // NOI18N
-            properties[PROPERTY_focusOwner] = new PropertyDescriptor ( "focusOwner", squidpony.squidgrid.gui.swing.SwingPane.class, "isFocusOwner", null ); // NOI18N
-            properties[PROPERTY_focusTraversable] = new PropertyDescriptor ( "focusTraversable", squidpony.squidgrid.gui.swing.SwingPane.class, "isFocusTraversable", null ); // NOI18N
-            properties[PROPERTY_focusTraversalKeys] = new IndexedPropertyDescriptor ( "focusTraversalKeys", squidpony.squidgrid.gui.swing.SwingPane.class, null, null, null, "setFocusTraversalKeys" ); // NOI18N
-            properties[PROPERTY_focusTraversalKeysEnabled] = new PropertyDescriptor ( "focusTraversalKeysEnabled", squidpony.squidgrid.gui.swing.SwingPane.class, "getFocusTraversalKeysEnabled", "setFocusTraversalKeysEnabled" ); // NOI18N
-            properties[PROPERTY_focusTraversalPolicy] = new PropertyDescriptor ( "focusTraversalPolicy", squidpony.squidgrid.gui.swing.SwingPane.class, "getFocusTraversalPolicy", "setFocusTraversalPolicy" ); // NOI18N
-            properties[PROPERTY_focusTraversalPolicyProvider] = new PropertyDescriptor ( "focusTraversalPolicyProvider", squidpony.squidgrid.gui.swing.SwingPane.class, "isFocusTraversalPolicyProvider", "setFocusTraversalPolicyProvider" ); // NOI18N
-            properties[PROPERTY_focusTraversalPolicySet] = new PropertyDescriptor ( "focusTraversalPolicySet", squidpony.squidgrid.gui.swing.SwingPane.class, "isFocusTraversalPolicySet", null ); // NOI18N
-            properties[PROPERTY_font] = new PropertyDescriptor ( "font", squidpony.squidgrid.gui.swing.SwingPane.class, "getFont", "setFont" ); // NOI18N
-            properties[PROPERTY_fontSet] = new PropertyDescriptor ( "fontSet", squidpony.squidgrid.gui.swing.SwingPane.class, "isFontSet", null ); // NOI18N
-            properties[PROPERTY_foreground] = new PropertyDescriptor ( "foreground", squidpony.squidgrid.gui.swing.SwingPane.class, "getForeground", "setForeground" ); // NOI18N
-            properties[PROPERTY_foregroundSet] = new PropertyDescriptor ( "foregroundSet", squidpony.squidgrid.gui.swing.SwingPane.class, "isForegroundSet", null ); // NOI18N
-            properties[PROPERTY_graphics] = new PropertyDescriptor ( "graphics", squidpony.squidgrid.gui.swing.SwingPane.class, "getGraphics", null ); // NOI18N
-            properties[PROPERTY_graphicsConfiguration] = new PropertyDescriptor ( "graphicsConfiguration", squidpony.squidgrid.gui.swing.SwingPane.class, "getGraphicsConfiguration", null ); // NOI18N
-            properties[PROPERTY_gridHeight] = new PropertyDescriptor ( "gridHeight", squidpony.squidgrid.gui.swing.SwingPane.class, "getGridHeight", null ); // NOI18N
-            properties[PROPERTY_gridWidth] = new PropertyDescriptor ( "gridWidth", squidpony.squidgrid.gui.swing.SwingPane.class, "getGridWidth", null ); // NOI18N
-            properties[PROPERTY_height] = new PropertyDescriptor ( "height", squidpony.squidgrid.gui.swing.SwingPane.class, "getHeight", null ); // NOI18N
-            properties[PROPERTY_hierarchyBoundsListeners] = new PropertyDescriptor ( "hierarchyBoundsListeners", squidpony.squidgrid.gui.swing.SwingPane.class, "getHierarchyBoundsListeners", null ); // NOI18N
-            properties[PROPERTY_hierarchyListeners] = new PropertyDescriptor ( "hierarchyListeners", squidpony.squidgrid.gui.swing.SwingPane.class, "getHierarchyListeners", null ); // NOI18N
-            properties[PROPERTY_ignoreRepaint] = new PropertyDescriptor ( "ignoreRepaint", squidpony.squidgrid.gui.swing.SwingPane.class, "getIgnoreRepaint", "setIgnoreRepaint" ); // NOI18N
-            properties[PROPERTY_imageCellMap] = new PropertyDescriptor ( "imageCellMap", squidpony.squidgrid.gui.swing.SwingPane.class, "getImageCellMap", "setImageCellMap" ); // NOI18N
-            properties[PROPERTY_inheritsPopupMenu] = new PropertyDescriptor ( "inheritsPopupMenu", squidpony.squidgrid.gui.swing.SwingPane.class, "getInheritsPopupMenu", "setInheritsPopupMenu" ); // NOI18N
-            properties[PROPERTY_inputContext] = new PropertyDescriptor ( "inputContext", squidpony.squidgrid.gui.swing.SwingPane.class, "getInputContext", null ); // NOI18N
-            properties[PROPERTY_inputMap] = new PropertyDescriptor ( "inputMap", squidpony.squidgrid.gui.swing.SwingPane.class, "getInputMap", null ); // NOI18N
-            properties[PROPERTY_inputMethodListeners] = new PropertyDescriptor ( "inputMethodListeners", squidpony.squidgrid.gui.swing.SwingPane.class, "getInputMethodListeners", null ); // NOI18N
-            properties[PROPERTY_inputMethodRequests] = new PropertyDescriptor ( "inputMethodRequests", squidpony.squidgrid.gui.swing.SwingPane.class, "getInputMethodRequests", null ); // NOI18N
-            properties[PROPERTY_inputVerifier] = new PropertyDescriptor ( "inputVerifier", squidpony.squidgrid.gui.swing.SwingPane.class, "getInputVerifier", "setInputVerifier" ); // NOI18N
-            properties[PROPERTY_insets] = new PropertyDescriptor ( "insets", squidpony.squidgrid.gui.swing.SwingPane.class, "getInsets", null ); // NOI18N
-            properties[PROPERTY_keyListeners] = new PropertyDescriptor ( "keyListeners", squidpony.squidgrid.gui.swing.SwingPane.class, "getKeyListeners", null ); // NOI18N
-            properties[PROPERTY_layout] = new PropertyDescriptor ( "layout", squidpony.squidgrid.gui.swing.SwingPane.class, "getLayout", "setLayout" ); // NOI18N
-            properties[PROPERTY_lightweight] = new PropertyDescriptor ( "lightweight", squidpony.squidgrid.gui.swing.SwingPane.class, "isLightweight", null ); // NOI18N
-            properties[PROPERTY_locale] = new PropertyDescriptor ( "locale", squidpony.squidgrid.gui.swing.SwingPane.class, "getLocale", "setLocale" ); // NOI18N
-            properties[PROPERTY_location] = new PropertyDescriptor ( "location", squidpony.squidgrid.gui.swing.SwingPane.class, "getLocation", "setLocation" ); // NOI18N
-            properties[PROPERTY_locationOnScreen] = new PropertyDescriptor ( "locationOnScreen", squidpony.squidgrid.gui.swing.SwingPane.class, "getLocationOnScreen", null ); // NOI18N
-            properties[PROPERTY_managingFocus] = new PropertyDescriptor ( "managingFocus", squidpony.squidgrid.gui.swing.SwingPane.class, "isManagingFocus", null ); // NOI18N
-            properties[PROPERTY_maximumSize] = new PropertyDescriptor ( "maximumSize", squidpony.squidgrid.gui.swing.SwingPane.class, "getMaximumSize", "setMaximumSize" ); // NOI18N
-            properties[PROPERTY_maximumSizeSet] = new PropertyDescriptor ( "maximumSizeSet", squidpony.squidgrid.gui.swing.SwingPane.class, "isMaximumSizeSet", null ); // NOI18N
-            properties[PROPERTY_minimumSize] = new PropertyDescriptor ( "minimumSize", squidpony.squidgrid.gui.swing.SwingPane.class, "getMinimumSize", "setMinimumSize" ); // NOI18N
-            properties[PROPERTY_minimumSizeSet] = new PropertyDescriptor ( "minimumSizeSet", squidpony.squidgrid.gui.swing.SwingPane.class, "isMinimumSizeSet", null ); // NOI18N
-            properties[PROPERTY_mouseListeners] = new PropertyDescriptor ( "mouseListeners", squidpony.squidgrid.gui.swing.SwingPane.class, "getMouseListeners", null ); // NOI18N
-            properties[PROPERTY_mouseMotionListeners] = new PropertyDescriptor ( "mouseMotionListeners", squidpony.squidgrid.gui.swing.SwingPane.class, "getMouseMotionListeners", null ); // NOI18N
-            properties[PROPERTY_mousePosition] = new PropertyDescriptor ( "mousePosition", squidpony.squidgrid.gui.swing.SwingPane.class, "getMousePosition", null ); // NOI18N
-            properties[PROPERTY_mouseWheelListeners] = new PropertyDescriptor ( "mouseWheelListeners", squidpony.squidgrid.gui.swing.SwingPane.class, "getMouseWheelListeners", null ); // NOI18N
-            properties[PROPERTY_name] = new PropertyDescriptor ( "name", squidpony.squidgrid.gui.swing.SwingPane.class, "getName", "setName" ); // NOI18N
-            properties[PROPERTY_nextFocusableComponent] = new PropertyDescriptor ( "nextFocusableComponent", squidpony.squidgrid.gui.swing.SwingPane.class, "getNextFocusableComponent", "setNextFocusableComponent" ); // NOI18N
-            properties[PROPERTY_opaque] = new PropertyDescriptor ( "opaque", squidpony.squidgrid.gui.swing.SwingPane.class, "isOpaque", "setOpaque" ); // NOI18N
-            properties[PROPERTY_optimizedDrawingEnabled] = new PropertyDescriptor ( "optimizedDrawingEnabled", squidpony.squidgrid.gui.swing.SwingPane.class, "isOptimizedDrawingEnabled", null ); // NOI18N
-            properties[PROPERTY_paintingForPrint] = new PropertyDescriptor ( "paintingForPrint", squidpony.squidgrid.gui.swing.SwingPane.class, "isPaintingForPrint", null ); // NOI18N
-            properties[PROPERTY_paintingTile] = new PropertyDescriptor ( "paintingTile", squidpony.squidgrid.gui.swing.SwingPane.class, "isPaintingTile", null ); // NOI18N
-            properties[PROPERTY_parent] = new PropertyDescriptor ( "parent", squidpony.squidgrid.gui.swing.SwingPane.class, "getParent", null ); // NOI18N
-            properties[PROPERTY_peer] = new PropertyDescriptor ( "peer", squidpony.squidgrid.gui.swing.SwingPane.class, "getPeer", null ); // NOI18N
-            properties[PROPERTY_preferredSize] = new PropertyDescriptor ( "preferredSize", squidpony.squidgrid.gui.swing.SwingPane.class, "getPreferredSize", "setPreferredSize" ); // NOI18N
-            properties[PROPERTY_preferredSizeSet] = new PropertyDescriptor ( "preferredSizeSet", squidpony.squidgrid.gui.swing.SwingPane.class, "isPreferredSizeSet", null ); // NOI18N
-            properties[PROPERTY_propertyChangeListeners] = new PropertyDescriptor ( "propertyChangeListeners", squidpony.squidgrid.gui.swing.SwingPane.class, "getPropertyChangeListeners", null ); // NOI18N
-            properties[PROPERTY_registeredKeyStrokes] = new PropertyDescriptor ( "registeredKeyStrokes", squidpony.squidgrid.gui.swing.SwingPane.class, "getRegisteredKeyStrokes", null ); // NOI18N
-            properties[PROPERTY_requestFocusEnabled] = new PropertyDescriptor ( "requestFocusEnabled", squidpony.squidgrid.gui.swing.SwingPane.class, "isRequestFocusEnabled", "setRequestFocusEnabled" ); // NOI18N
-            properties[PROPERTY_rootPane] = new PropertyDescriptor ( "rootPane", squidpony.squidgrid.gui.swing.SwingPane.class, "getRootPane", null ); // NOI18N
-            properties[PROPERTY_showing] = new PropertyDescriptor ( "showing", squidpony.squidgrid.gui.swing.SwingPane.class, "isShowing", null ); // NOI18N
-            properties[PROPERTY_size] = new PropertyDescriptor ( "size", squidpony.squidgrid.gui.swing.SwingPane.class, "getSize", "setSize" ); // NOI18N
-            properties[PROPERTY_text] = new PropertyDescriptor ( "text", squidpony.squidgrid.gui.swing.SwingPane.class, null, "setText" ); // NOI18N
-            properties[PROPERTY_textCellFactory] = new PropertyDescriptor ( "textCellFactory", squidpony.squidgrid.gui.swing.SwingPane.class, null, "setTextCellFactory" ); // NOI18N
-            properties[PROPERTY_textFactory] = new PropertyDescriptor ( "textFactory", squidpony.squidgrid.gui.swing.SwingPane.class, "getTextFactory", null ); // NOI18N
-            properties[PROPERTY_toolkit] = new PropertyDescriptor ( "toolkit", squidpony.squidgrid.gui.swing.SwingPane.class, "getToolkit", null ); // NOI18N
-            properties[PROPERTY_toolTipText] = new PropertyDescriptor ( "toolTipText", squidpony.squidgrid.gui.swing.SwingPane.class, "getToolTipText", "setToolTipText" ); // NOI18N
-            properties[PROPERTY_topLevelAncestor] = new PropertyDescriptor ( "topLevelAncestor", squidpony.squidgrid.gui.swing.SwingPane.class, "getTopLevelAncestor", null ); // NOI18N
-            properties[PROPERTY_transferHandler] = new PropertyDescriptor ( "transferHandler", squidpony.squidgrid.gui.swing.SwingPane.class, "getTransferHandler", "setTransferHandler" ); // NOI18N
-            properties[PROPERTY_treeLock] = new PropertyDescriptor ( "treeLock", squidpony.squidgrid.gui.swing.SwingPane.class, "getTreeLock", null ); // NOI18N
-            properties[PROPERTY_UIClassID] = new PropertyDescriptor ( "UIClassID", squidpony.squidgrid.gui.swing.SwingPane.class, "getUIClassID", null ); // NOI18N
-            properties[PROPERTY_valid] = new PropertyDescriptor ( "valid", squidpony.squidgrid.gui.swing.SwingPane.class, "isValid", null ); // NOI18N
-            properties[PROPERTY_validateRoot] = new PropertyDescriptor ( "validateRoot", squidpony.squidgrid.gui.swing.SwingPane.class, "isValidateRoot", null ); // NOI18N
-            properties[PROPERTY_verifyInputWhenFocusTarget] = new PropertyDescriptor ( "verifyInputWhenFocusTarget", squidpony.squidgrid.gui.swing.SwingPane.class, "getVerifyInputWhenFocusTarget", "setVerifyInputWhenFocusTarget" ); // NOI18N
-            properties[PROPERTY_vetoableChangeListeners] = new PropertyDescriptor ( "vetoableChangeListeners", squidpony.squidgrid.gui.swing.SwingPane.class, "getVetoableChangeListeners", null ); // NOI18N
-            properties[PROPERTY_visible] = new PropertyDescriptor ( "visible", squidpony.squidgrid.gui.swing.SwingPane.class, "isVisible", "setVisible" ); // NOI18N
-            properties[PROPERTY_visibleRect] = new PropertyDescriptor ( "visibleRect", squidpony.squidgrid.gui.swing.SwingPane.class, "getVisibleRect", null ); // NOI18N
-            properties[PROPERTY_width] = new PropertyDescriptor ( "width", squidpony.squidgrid.gui.swing.SwingPane.class, "getWidth", null ); // NOI18N
-            properties[PROPERTY_x] = new PropertyDescriptor ( "x", squidpony.squidgrid.gui.swing.SwingPane.class, "getX", null ); // NOI18N
-            properties[PROPERTY_y] = new PropertyDescriptor ( "y", squidpony.squidgrid.gui.swing.SwingPane.class, "getY", null ); // NOI18N
-        }
-        catch(IntrospectionException e) {
-            e.printStackTrace();
-        }//GEN-HEADEREND:Properties
-
-        // Here you can add code for customizing the properties array.
-
-        return properties;     }//GEN-LAST:Properties
-    // EventSet identifiers//GEN-FIRST:Events
-    private static final int EVENT_ancestorListener = 0;
-    private static final int EVENT_componentListener = 1;
-    private static final int EVENT_containerListener = 2;
-    private static final int EVENT_focusListener = 3;
-    private static final int EVENT_hierarchyBoundsListener = 4;
-    private static final int EVENT_hierarchyListener = 5;
-    private static final int EVENT_inputMethodListener = 6;
-    private static final int EVENT_keyListener = 7;
-    private static final int EVENT_mouseListener = 8;
-    private static final int EVENT_mouseMotionListener = 9;
-    private static final int EVENT_mouseWheelListener = 10;
-    private static final int EVENT_propertyChangeListener = 11;
-    private static final int EVENT_vetoableChangeListener = 12;
-
-    // EventSet array
-    /*lazy EventSetDescriptor*/
-    private static EventSetDescriptor[] getEdescriptor(){
-        EventSetDescriptor[] eventSets = new EventSetDescriptor[13];
-    
-        try {
-            eventSets[EVENT_ancestorListener] = new EventSetDescriptor ( squidpony.squidgrid.gui.swing.SwingPane.class, "ancestorListener", javax.swing.event.AncestorListener.class, new String[] {"ancestorAdded", "ancestorRemoved", "ancestorMoved"}, "addAncestorListener", "removeAncestorListener" ); // NOI18N
-            eventSets[EVENT_componentListener] = new EventSetDescriptor ( squidpony.squidgrid.gui.swing.SwingPane.class, "componentListener", java.awt.event.ComponentListener.class, new String[] {"componentResized", "componentMoved", "componentShown", "componentHidden"}, "addComponentListener", "removeComponentListener" ); // NOI18N
-            eventSets[EVENT_containerListener] = new EventSetDescriptor ( squidpony.squidgrid.gui.swing.SwingPane.class, "containerListener", java.awt.event.ContainerListener.class, new String[] {"componentAdded", "componentRemoved"}, "addContainerListener", "removeContainerListener" ); // NOI18N
-            eventSets[EVENT_focusListener] = new EventSetDescriptor ( squidpony.squidgrid.gui.swing.SwingPane.class, "focusListener", java.awt.event.FocusListener.class, new String[] {"focusGained", "focusLost"}, "addFocusListener", "removeFocusListener" ); // NOI18N
-            eventSets[EVENT_hierarchyBoundsListener] = new EventSetDescriptor ( squidpony.squidgrid.gui.swing.SwingPane.class, "hierarchyBoundsListener", java.awt.event.HierarchyBoundsListener.class, new String[] {"ancestorMoved", "ancestorResized"}, "addHierarchyBoundsListener", "removeHierarchyBoundsListener" ); // NOI18N
-            eventSets[EVENT_hierarchyListener] = new EventSetDescriptor ( squidpony.squidgrid.gui.swing.SwingPane.class, "hierarchyListener", java.awt.event.HierarchyListener.class, new String[] {"hierarchyChanged"}, "addHierarchyListener", "removeHierarchyListener" ); // NOI18N
-            eventSets[EVENT_inputMethodListener] = new EventSetDescriptor ( squidpony.squidgrid.gui.swing.SwingPane.class, "inputMethodListener", java.awt.event.InputMethodListener.class, new String[] {"inputMethodTextChanged", "caretPositionChanged"}, "addInputMethodListener", "removeInputMethodListener" ); // NOI18N
-            eventSets[EVENT_keyListener] = new EventSetDescriptor ( squidpony.squidgrid.gui.swing.SwingPane.class, "keyListener", java.awt.event.KeyListener.class, new String[] {"keyTyped", "keyPressed", "keyReleased"}, "addKeyListener", "removeKeyListener" ); // NOI18N
-            eventSets[EVENT_mouseListener] = new EventSetDescriptor ( squidpony.squidgrid.gui.swing.SwingPane.class, "mouseListener", java.awt.event.MouseListener.class, new String[] {"mouseClicked", "mousePressed", "mouseReleased", "mouseEntered", "mouseExited"}, "addMouseListener", "removeMouseListener" ); // NOI18N
-            eventSets[EVENT_mouseMotionListener] = new EventSetDescriptor ( squidpony.squidgrid.gui.swing.SwingPane.class, "mouseMotionListener", java.awt.event.MouseMotionListener.class, new String[] {"mouseDragged", "mouseMoved"}, "addMouseMotionListener", "removeMouseMotionListener" ); // NOI18N
-            eventSets[EVENT_mouseWheelListener] = new EventSetDescriptor ( squidpony.squidgrid.gui.swing.SwingPane.class, "mouseWheelListener", java.awt.event.MouseWheelListener.class, new String[] {"mouseWheelMoved"}, "addMouseWheelListener", "removeMouseWheelListener" ); // NOI18N
-            eventSets[EVENT_propertyChangeListener] = new EventSetDescriptor ( squidpony.squidgrid.gui.swing.SwingPane.class, "propertyChangeListener", java.beans.PropertyChangeListener.class, new String[] {"propertyChange"}, "addPropertyChangeListener", "removePropertyChangeListener" ); // NOI18N
-            eventSets[EVENT_vetoableChangeListener] = new EventSetDescriptor ( squidpony.squidgrid.gui.swing.SwingPane.class, "vetoableChangeListener", java.beans.VetoableChangeListener.class, new String[] {"vetoableChange"}, "addVetoableChangeListener", "removeVetoableChangeListener" ); // NOI18N
-        }
-        catch(IntrospectionException e) {
-            e.printStackTrace();
-        }//GEN-HEADEREND:Events
-
-        // Here you can add code for customizing the event sets array.
-
-        return eventSets;     }//GEN-LAST:Events
-    // Method identifiers//GEN-FIRST:Methods
-    private static final int METHOD_action0 = 0;
-    private static final int METHOD_add1 = 1;
-    private static final int METHOD_add2 = 2;
-    private static final int METHOD_add3 = 3;
-    private static final int METHOD_add4 = 4;
-    private static final int METHOD_add5 = 5;
-    private static final int METHOD_add6 = 6;
-    private static final int METHOD_addNotify7 = 7;
-    private static final int METHOD_addPropertyChangeListener8 = 8;
-    private static final int METHOD_applyComponentOrientation9 = 9;
-    private static final int METHOD_areFocusTraversalKeysSet10 = 10;
-    private static final int METHOD_bounds11 = 11;
-    private static final int METHOD_bump12 = 12;
-    private static final int METHOD_bump13 = 13;
-    private static final int METHOD_checkImage14 = 14;
-    private static final int METHOD_checkImage15 = 15;
-    private static final int METHOD_clearCell16 = 16;
-    private static final int METHOD_clearCell17 = 17;
-    private static final int METHOD_computeVisibleRect18 = 18;
-    private static final int METHOD_contains19 = 19;
-    private static final int METHOD_contains20 = 20;
-    private static final int METHOD_countComponents21 = 21;
-    private static final int METHOD_createImage22 = 22;
-    private static final int METHOD_createImage23 = 23;
-    private static final int METHOD_createToolTip24 = 24;
-    private static final int METHOD_createVolatileImage25 = 25;
-    private static final int METHOD_createVolatileImage26 = 26;
-    private static final int METHOD_deliverEvent27 = 27;
-    private static final int METHOD_disable28 = 28;
-    private static final int METHOD_dispatchEvent29 = 29;
-    private static final int METHOD_doLayout30 = 30;
-    private static final int METHOD_enable31 = 31;
-    private static final int METHOD_enable32 = 32;
-    private static final int METHOD_enableInputMethods33 = 33;
-    private static final int METHOD_ensureFits34 = 34;
-    private static final int METHOD_findComponentAt35 = 35;
-    private static final int METHOD_findComponentAt36 = 36;
-    private static final int METHOD_firePropertyChange37 = 37;
-    private static final int METHOD_firePropertyChange38 = 38;
-    private static final int METHOD_firePropertyChange39 = 39;
-    private static final int METHOD_firePropertyChange40 = 40;
-    private static final int METHOD_firePropertyChange41 = 41;
-    private static final int METHOD_firePropertyChange42 = 42;
-    private static final int METHOD_firePropertyChange43 = 43;
-    private static final int METHOD_firePropertyChange44 = 44;
-    private static final int METHOD_getActionForKeyStroke45 = 45;
-    private static final int METHOD_getBaseline46 = 46;
-    private static final int METHOD_getBounds47 = 47;
-    private static final int METHOD_getClientProperty48 = 48;
-    private static final int METHOD_getComponentAt49 = 49;
-    private static final int METHOD_getComponentAt50 = 50;
-    private static final int METHOD_getComponentZOrder51 = 51;
-    private static final int METHOD_getConditionForKeyStroke52 = 52;
-    private static final int METHOD_getDefaultLocale53 = 53;
-    private static final int METHOD_getFocusTraversalKeys54 = 54;
-    private static final int METHOD_getFontMetrics55 = 55;
-    private static final int METHOD_getIndexOf56 = 56;
-    private static final int METHOD_getInsets57 = 57;
-    private static final int METHOD_getLayer58 = 58;
-    private static final int METHOD_getLayer59 = 59;
-    private static final int METHOD_getLayeredPaneAbove60 = 60;
-    private static final int METHOD_getListeners61 = 61;
-    private static final int METHOD_getLocation62 = 62;
-    private static final int METHOD_getMousePosition63 = 63;
-    private static final int METHOD_getPopupLocation64 = 64;
-    private static final int METHOD_getPosition65 = 65;
-    private static final int METHOD_getPropertyChangeListeners66 = 66;
-    private static final int METHOD_getSize67 = 67;
-    private static final int METHOD_getToolTipLocation68 = 68;
-    private static final int METHOD_getToolTipText69 = 69;
-    private static final int METHOD_gotFocus70 = 70;
-    private static final int METHOD_grabFocus71 = 71;
-    private static final int METHOD_handleEvent72 = 72;
-    private static final int METHOD_hasFocus73 = 73;
-    private static final int METHOD_hide74 = 74;
-    private static final int METHOD_highestLayer75 = 75;
-    private static final int METHOD_imageUpdate76 = 76;
-    private static final int METHOD_initialize77 = 77;
-    private static final int METHOD_initialize78 = 78;
-    private static final int METHOD_insets79 = 79;
-    private static final int METHOD_inside80 = 80;
-    private static final int METHOD_invalidate81 = 81;
-    private static final int METHOD_isAncestorOf82 = 82;
-    private static final int METHOD_isFocusCycleRoot83 = 83;
-    private static final int METHOD_isLightweightComponent84 = 84;
-    private static final int METHOD_keyDown85 = 85;
-    private static final int METHOD_keyUp86 = 86;
-    private static final int METHOD_layout87 = 87;
-    private static final int METHOD_list88 = 88;
-    private static final int METHOD_list89 = 89;
-    private static final int METHOD_list90 = 90;
-    private static final int METHOD_list91 = 91;
-    private static final int METHOD_list92 = 92;
-    private static final int METHOD_locate93 = 93;
-    private static final int METHOD_location94 = 94;
-    private static final int METHOD_lostFocus95 = 95;
-    private static final int METHOD_lowestLayer96 = 96;
-    private static final int METHOD_minimumSize97 = 97;
-    private static final int METHOD_mouseDown98 = 98;
-    private static final int METHOD_mouseDrag99 = 99;
-    private static final int METHOD_mouseEnter100 = 100;
-    private static final int METHOD_mouseExit101 = 101;
-    private static final int METHOD_mouseMove102 = 102;
-    private static final int METHOD_mouseUp103 = 103;
-    private static final int METHOD_move104 = 104;
-    private static final int METHOD_moveToBack105 = 105;
-    private static final int METHOD_moveToFront106 = 106;
-    private static final int METHOD_nextFocus107 = 107;
-    private static final int METHOD_paint108 = 108;
-    private static final int METHOD_paintAll109 = 109;
-    private static final int METHOD_paintComponent110 = 110;
-    private static final int METHOD_paintComponents111 = 111;
-    private static final int METHOD_paintImmediately112 = 112;
-    private static final int METHOD_paintImmediately113 = 113;
-    private static final int METHOD_placeCharacter114 = 114;
-    private static final int METHOD_placeCharacter115 = 115;
-    private static final int METHOD_placeCharacter116 = 116;
-    private static final int METHOD_placeHorizontalString117 = 117;
-    private static final int METHOD_placeHorizontalString118 = 118;
-    private static final int METHOD_placeImage119 = 119;
-    private static final int METHOD_placeImage120 = 120;
-    private static final int METHOD_placeText121 = 121;
-    private static final int METHOD_placeText122 = 122;
-    private static final int METHOD_placeVerticalString123 = 123;
-    private static final int METHOD_placeVerticalString124 = 124;
-    private static final int METHOD_postEvent125 = 125;
-    private static final int METHOD_preferredSize126 = 126;
-    private static final int METHOD_prepareImage127 = 127;
-    private static final int METHOD_prepareImage128 = 128;
-    private static final int METHOD_print129 = 129;
-    private static final int METHOD_printAll130 = 130;
-    private static final int METHOD_printComponents131 = 131;
-    private static final int METHOD_putClientProperty132 = 132;
-    private static final int METHOD_putLayer133 = 133;
-    private static final int METHOD_refresh134 = 134;
-    private static final int METHOD_registerKeyboardAction135 = 135;
-    private static final int METHOD_registerKeyboardAction136 = 136;
-    private static final int METHOD_remove137 = 137;
-    private static final int METHOD_remove138 = 138;
-    private static final int METHOD_remove139 = 139;
-    private static final int METHOD_removeAll140 = 140;
-    private static final int METHOD_removeNotify141 = 141;
-    private static final int METHOD_removePropertyChangeListener142 = 142;
-    private static final int METHOD_repaint143 = 143;
-    private static final int METHOD_repaint144 = 144;
-    private static final int METHOD_repaint145 = 145;
-    private static final int METHOD_repaint146 = 146;
-    private static final int METHOD_repaint147 = 147;
-    private static final int METHOD_requestDefaultFocus148 = 148;
-    private static final int METHOD_requestFocus149 = 149;
-    private static final int METHOD_requestFocus150 = 150;
-    private static final int METHOD_requestFocusInWindow151 = 151;
-    private static final int METHOD_resetKeyboardActions152 = 152;
-    private static final int METHOD_reshape153 = 153;
-    private static final int METHOD_resize154 = 154;
-    private static final int METHOD_resize155 = 155;
-    private static final int METHOD_revalidate156 = 156;
-    private static final int METHOD_scrollRectToVisible157 = 157;
-    private static final int METHOD_setBounds158 = 158;
-    private static final int METHOD_setComponentZOrder159 = 159;
-    private static final int METHOD_setDefaultLocale160 = 160;
-    private static final int METHOD_setLayer161 = 161;
-    private static final int METHOD_setLayer162 = 162;
-    private static final int METHOD_setPosition163 = 163;
-    private static final int METHOD_show164 = 164;
-    private static final int METHOD_show165 = 165;
-    private static final int METHOD_size166 = 166;
-    private static final int METHOD_slide167 = 167;
-    private static final int METHOD_slide168 = 168;
-    private static final int METHOD_slide169 = 169;
-    private static final int METHOD_toString170 = 170;
-    private static final int METHOD_transferFocus171 = 171;
-    private static final int METHOD_transferFocusBackward172 = 172;
-    private static final int METHOD_transferFocusDownCycle173 = 173;
-    private static final int METHOD_transferFocusUpCycle174 = 174;
-    private static final int METHOD_unregisterKeyboardAction175 = 175;
-    private static final int METHOD_update176 = 176;
-    private static final int METHOD_updateUI177 = 177;
-    private static final int METHOD_validate178 = 178;
-    private static final int METHOD_waitForAnimations179 = 179;
-    private static final int METHOD_wiggle180 = 180;
-    private static final int METHOD_willFit181 = 181;
-
-    // Method array 
-    /*lazy MethodDescriptor*/
-    private static MethodDescriptor[] getMdescriptor(){
-        MethodDescriptor[] methods = new MethodDescriptor[182];
-    
-        try {
-            methods[METHOD_action0] = new MethodDescriptor(java.awt.Component.class.getMethod("action", new Class[] {java.awt.Event.class, java.lang.Object.class})); // NOI18N
-            methods[METHOD_action0].setHidden ( true );
-            methods[METHOD_action0].setDisplayName ( "" );
-            methods[METHOD_add1] = new MethodDescriptor(java.awt.Component.class.getMethod("add", new Class[] {java.awt.PopupMenu.class})); // NOI18N
-            methods[METHOD_add1].setHidden ( true );
-            methods[METHOD_add1].setDisplayName ( "" );
-            methods[METHOD_add2] = new MethodDescriptor(java.awt.Container.class.getMethod("add", new Class[] {java.awt.Component.class})); // NOI18N
-            methods[METHOD_add2].setHidden ( true );
-            methods[METHOD_add2].setDisplayName ( "" );
-            methods[METHOD_add3] = new MethodDescriptor(java.awt.Container.class.getMethod("add", new Class[] {java.lang.String.class, java.awt.Component.class})); // NOI18N
-            methods[METHOD_add3].setHidden ( true );
-            methods[METHOD_add3].setDisplayName ( "" );
-            methods[METHOD_add4] = new MethodDescriptor(java.awt.Container.class.getMethod("add", new Class[] {java.awt.Component.class, int.class})); // NOI18N
-            methods[METHOD_add4].setHidden ( true );
-            methods[METHOD_add4].setDisplayName ( "" );
-            methods[METHOD_add5] = new MethodDescriptor(java.awt.Container.class.getMethod("add", new Class[] {java.awt.Component.class, java.lang.Object.class})); // NOI18N
-            methods[METHOD_add5].setHidden ( true );
-            methods[METHOD_add5].setDisplayName ( "" );
-            methods[METHOD_add6] = new MethodDescriptor(java.awt.Container.class.getMethod("add", new Class[] {java.awt.Component.class, java.lang.Object.class, int.class})); // NOI18N
-            methods[METHOD_add6].setHidden ( true );
-            methods[METHOD_add6].setDisplayName ( "" );
-            methods[METHOD_addNotify7] = new MethodDescriptor(javax.swing.JComponent.class.getMethod("addNotify", new Class[] {})); // NOI18N
-            methods[METHOD_addNotify7].setHidden ( true );
-            methods[METHOD_addNotify7].setDisplayName ( "" );
-            methods[METHOD_addPropertyChangeListener8] = new MethodDescriptor(java.awt.Container.class.getMethod("addPropertyChangeListener", new Class[] {java.lang.String.class, java.beans.PropertyChangeListener.class})); // NOI18N
-            methods[METHOD_addPropertyChangeListener8].setHidden ( true );
-            methods[METHOD_addPropertyChangeListener8].setDisplayName ( "" );
-            methods[METHOD_applyComponentOrientation9] = new MethodDescriptor(java.awt.Container.class.getMethod("applyComponentOrientation", new Class[] {java.awt.ComponentOrientation.class})); // NOI18N
-            methods[METHOD_applyComponentOrientation9].setHidden ( true );
-            methods[METHOD_applyComponentOrientation9].setDisplayName ( "" );
-            methods[METHOD_areFocusTraversalKeysSet10] = new MethodDescriptor(java.awt.Container.class.getMethod("areFocusTraversalKeysSet", new Class[] {int.class})); // NOI18N
-            methods[METHOD_areFocusTraversalKeysSet10].setHidden ( true );
-            methods[METHOD_areFocusTraversalKeysSet10].setDisplayName ( "" );
-            methods[METHOD_bounds11] = new MethodDescriptor(java.awt.Component.class.getMethod("bounds", new Class[] {})); // NOI18N
-            methods[METHOD_bounds11].setDisplayName ( "" );
-            methods[METHOD_bump12] = new MethodDescriptor(squidpony.squidgrid.gui.swing.SwingPane.class.getMethod("bump", new Class[] {java.awt.Point.class, squidpony.squidgrid.util.Direction.class})); // NOI18N
-            methods[METHOD_bump12].setDisplayName ( "" );
-            methods[METHOD_bump13] = new MethodDescriptor(squidpony.squidgrid.gui.swing.SwingPane.class.getMethod("bump", new Class[] {java.awt.Point.class, java.awt.Point.class})); // NOI18N
-            methods[METHOD_bump13].setDisplayName ( "" );
-            methods[METHOD_checkImage14] = new MethodDescriptor(java.awt.Component.class.getMethod("checkImage", new Class[] {java.awt.Image.class, java.awt.image.ImageObserver.class})); // NOI18N
-            methods[METHOD_checkImage14].setHidden ( true );
-            methods[METHOD_checkImage14].setDisplayName ( "" );
-            methods[METHOD_checkImage15] = new MethodDescriptor(java.awt.Component.class.getMethod("checkImage", new Class[] {java.awt.Image.class, int.class, int.class, java.awt.image.ImageObserver.class})); // NOI18N
-            methods[METHOD_checkImage15].setHidden ( true );
-            methods[METHOD_checkImage15].setDisplayName ( "" );
-            methods[METHOD_clearCell16] = new MethodDescriptor(squidpony.squidgrid.gui.swing.SwingPane.class.getMethod("clearCell", new Class[] {int.class, int.class})); // NOI18N
-            methods[METHOD_clearCell16].setDisplayName ( "" );
-            methods[METHOD_clearCell17] = new MethodDescriptor(squidpony.squidgrid.gui.swing.SwingPane.class.getMethod("clearCell", new Class[] {int.class, int.class, java.awt.Color.class})); // NOI18N
-            methods[METHOD_clearCell17].setDisplayName ( "" );
-            methods[METHOD_computeVisibleRect18] = new MethodDescriptor(javax.swing.JComponent.class.getMethod("computeVisibleRect", new Class[] {java.awt.Rectangle.class})); // NOI18N
-            methods[METHOD_computeVisibleRect18].setDisplayName ( "" );
-            methods[METHOD_contains19] = new MethodDescriptor(java.awt.Component.class.getMethod("contains", new Class[] {java.awt.Point.class})); // NOI18N
-            methods[METHOD_contains19].setDisplayName ( "" );
-            methods[METHOD_contains20] = new MethodDescriptor(javax.swing.JComponent.class.getMethod("contains", new Class[] {int.class, int.class})); // NOI18N
-            methods[METHOD_contains20].setDisplayName ( "" );
-            methods[METHOD_countComponents21] = new MethodDescriptor(java.awt.Container.class.getMethod("countComponents", new Class[] {})); // NOI18N
-            methods[METHOD_countComponents21].setDisplayName ( "" );
-            methods[METHOD_createImage22] = new MethodDescriptor(java.awt.Component.class.getMethod("createImage", new Class[] {java.awt.image.ImageProducer.class})); // NOI18N
-            methods[METHOD_createImage22].setDisplayName ( "" );
-            methods[METHOD_createImage23] = new MethodDescriptor(java.awt.Component.class.getMethod("createImage", new Class[] {int.class, int.class})); // NOI18N
-            methods[METHOD_createImage23].setDisplayName ( "" );
-            methods[METHOD_createToolTip24] = new MethodDescriptor(javax.swing.JComponent.class.getMethod("createToolTip", new Class[] {})); // NOI18N
-            methods[METHOD_createToolTip24].setDisplayName ( "" );
-            methods[METHOD_createVolatileImage25] = new MethodDescriptor(java.awt.Component.class.getMethod("createVolatileImage", new Class[] {int.class, int.class})); // NOI18N
-            methods[METHOD_createVolatileImage25].setDisplayName ( "" );
-            methods[METHOD_createVolatileImage26] = new MethodDescriptor(java.awt.Component.class.getMethod("createVolatileImage", new Class[] {int.class, int.class, java.awt.ImageCapabilities.class})); // NOI18N
-            methods[METHOD_createVolatileImage26].setDisplayName ( "" );
-            methods[METHOD_deliverEvent27] = new MethodDescriptor(java.awt.Container.class.getMethod("deliverEvent", new Class[] {java.awt.Event.class})); // NOI18N
-            methods[METHOD_deliverEvent27].setDisplayName ( "" );
-            methods[METHOD_disable28] = new MethodDescriptor(javax.swing.JComponent.class.getMethod("disable", new Class[] {})); // NOI18N
-            methods[METHOD_disable28].setDisplayName ( "" );
-            methods[METHOD_dispatchEvent29] = new MethodDescriptor(java.awt.Component.class.getMethod("dispatchEvent", new Class[] {java.awt.AWTEvent.class})); // NOI18N
-            methods[METHOD_dispatchEvent29].setDisplayName ( "" );
-            methods[METHOD_doLayout30] = new MethodDescriptor(java.awt.Container.class.getMethod("doLayout", new Class[] {})); // NOI18N
-            methods[METHOD_doLayout30].setDisplayName ( "" );
-            methods[METHOD_enable31] = new MethodDescriptor(java.awt.Component.class.getMethod("enable", new Class[] {boolean.class})); // NOI18N
-            methods[METHOD_enable31].setDisplayName ( "" );
-            methods[METHOD_enable32] = new MethodDescriptor(javax.swing.JComponent.class.getMethod("enable", new Class[] {})); // NOI18N
-            methods[METHOD_enable32].setDisplayName ( "" );
-            methods[METHOD_enableInputMethods33] = new MethodDescriptor(java.awt.Component.class.getMethod("enableInputMethods", new Class[] {boolean.class})); // NOI18N
-            methods[METHOD_enableInputMethods33].setDisplayName ( "" );
-            methods[METHOD_ensureFits34] = new MethodDescriptor(squidpony.squidgrid.gui.swing.SwingPane.class.getMethod("ensureFits", new Class[] {char[].class})); // NOI18N
-            methods[METHOD_ensureFits34].setDisplayName ( "" );
-            methods[METHOD_findComponentAt35] = new MethodDescriptor(java.awt.Container.class.getMethod("findComponentAt", new Class[] {int.class, int.class})); // NOI18N
-            methods[METHOD_findComponentAt35].setDisplayName ( "" );
-            methods[METHOD_findComponentAt36] = new MethodDescriptor(java.awt.Container.class.getMethod("findComponentAt", new Class[] {java.awt.Point.class})); // NOI18N
-            methods[METHOD_findComponentAt36].setDisplayName ( "" );
-            methods[METHOD_firePropertyChange37] = new MethodDescriptor(java.awt.Component.class.getMethod("firePropertyChange", new Class[] {java.lang.String.class, byte.class, byte.class})); // NOI18N
-            methods[METHOD_firePropertyChange37].setDisplayName ( "" );
-            methods[METHOD_firePropertyChange38] = new MethodDescriptor(java.awt.Component.class.getMethod("firePropertyChange", new Class[] {java.lang.String.class, short.class, short.class})); // NOI18N
-            methods[METHOD_firePropertyChange38].setDisplayName ( "" );
-            methods[METHOD_firePropertyChange39] = new MethodDescriptor(java.awt.Component.class.getMethod("firePropertyChange", new Class[] {java.lang.String.class, long.class, long.class})); // NOI18N
-            methods[METHOD_firePropertyChange39].setDisplayName ( "" );
-            methods[METHOD_firePropertyChange40] = new MethodDescriptor(java.awt.Component.class.getMethod("firePropertyChange", new Class[] {java.lang.String.class, float.class, float.class})); // NOI18N
-            methods[METHOD_firePropertyChange40].setDisplayName ( "" );
-            methods[METHOD_firePropertyChange41] = new MethodDescriptor(java.awt.Component.class.getMethod("firePropertyChange", new Class[] {java.lang.String.class, double.class, double.class})); // NOI18N
-            methods[METHOD_firePropertyChange41].setDisplayName ( "" );
-            methods[METHOD_firePropertyChange42] = new MethodDescriptor(javax.swing.JComponent.class.getMethod("firePropertyChange", new Class[] {java.lang.String.class, boolean.class, boolean.class})); // NOI18N
-            methods[METHOD_firePropertyChange42].setDisplayName ( "" );
-            methods[METHOD_firePropertyChange43] = new MethodDescriptor(javax.swing.JComponent.class.getMethod("firePropertyChange", new Class[] {java.lang.String.class, int.class, int.class})); // NOI18N
-            methods[METHOD_firePropertyChange43].setDisplayName ( "" );
-            methods[METHOD_firePropertyChange44] = new MethodDescriptor(javax.swing.JComponent.class.getMethod("firePropertyChange", new Class[] {java.lang.String.class, char.class, char.class})); // NOI18N
-            methods[METHOD_firePropertyChange44].setDisplayName ( "" );
-            methods[METHOD_getActionForKeyStroke45] = new MethodDescriptor(javax.swing.JComponent.class.getMethod("getActionForKeyStroke", new Class[] {javax.swing.KeyStroke.class})); // NOI18N
-            methods[METHOD_getActionForKeyStroke45].setDisplayName ( "" );
-            methods[METHOD_getBaseline46] = new MethodDescriptor(javax.swing.JComponent.class.getMethod("getBaseline", new Class[] {int.class, int.class})); // NOI18N
-            methods[METHOD_getBaseline46].setDisplayName ( "" );
-            methods[METHOD_getBounds47] = new MethodDescriptor(javax.swing.JComponent.class.getMethod("getBounds", new Class[] {java.awt.Rectangle.class})); // NOI18N
-            methods[METHOD_getBounds47].setDisplayName ( "" );
-            methods[METHOD_getClientProperty48] = new MethodDescriptor(javax.swing.JComponent.class.getMethod("getClientProperty", new Class[] {java.lang.Object.class})); // NOI18N
-            methods[METHOD_getClientProperty48].setDisplayName ( "" );
-            methods[METHOD_getComponentAt49] = new MethodDescriptor(java.awt.Container.class.getMethod("getComponentAt", new Class[] {int.class, int.class})); // NOI18N
-            methods[METHOD_getComponentAt49].setDisplayName ( "" );
-            methods[METHOD_getComponentAt50] = new MethodDescriptor(java.awt.Container.class.getMethod("getComponentAt", new Class[] {java.awt.Point.class})); // NOI18N
-            methods[METHOD_getComponentAt50].setDisplayName ( "" );
-            methods[METHOD_getComponentZOrder51] = new MethodDescriptor(java.awt.Container.class.getMethod("getComponentZOrder", new Class[] {java.awt.Component.class})); // NOI18N
-            methods[METHOD_getComponentZOrder51].setDisplayName ( "" );
-            methods[METHOD_getConditionForKeyStroke52] = new MethodDescriptor(javax.swing.JComponent.class.getMethod("getConditionForKeyStroke", new Class[] {javax.swing.KeyStroke.class})); // NOI18N
-            methods[METHOD_getConditionForKeyStroke52].setDisplayName ( "" );
-            methods[METHOD_getDefaultLocale53] = new MethodDescriptor(javax.swing.JComponent.class.getMethod("getDefaultLocale", new Class[] {})); // NOI18N
-            methods[METHOD_getDefaultLocale53].setDisplayName ( "" );
-            methods[METHOD_getFocusTraversalKeys54] = new MethodDescriptor(java.awt.Container.class.getMethod("getFocusTraversalKeys", new Class[] {int.class})); // NOI18N
-            methods[METHOD_getFocusTraversalKeys54].setDisplayName ( "" );
-            methods[METHOD_getFontMetrics55] = new MethodDescriptor(javax.swing.JComponent.class.getMethod("getFontMetrics", new Class[] {java.awt.Font.class})); // NOI18N
-            methods[METHOD_getFontMetrics55].setDisplayName ( "" );
-            methods[METHOD_getIndexOf56] = new MethodDescriptor(javax.swing.JLayeredPane.class.getMethod("getIndexOf", new Class[] {java.awt.Component.class})); // NOI18N
-            methods[METHOD_getIndexOf56].setDisplayName ( "" );
-            methods[METHOD_getInsets57] = new MethodDescriptor(javax.swing.JComponent.class.getMethod("getInsets", new Class[] {java.awt.Insets.class})); // NOI18N
-            methods[METHOD_getInsets57].setDisplayName ( "" );
-            methods[METHOD_getLayer58] = new MethodDescriptor(javax.swing.JLayeredPane.class.getMethod("getLayer", new Class[] {javax.swing.JComponent.class})); // NOI18N
-            methods[METHOD_getLayer58].setDisplayName ( "" );
-            methods[METHOD_getLayer59] = new MethodDescriptor(javax.swing.JLayeredPane.class.getMethod("getLayer", new Class[] {java.awt.Component.class})); // NOI18N
-            methods[METHOD_getLayer59].setDisplayName ( "" );
-            methods[METHOD_getLayeredPaneAbove60] = new MethodDescriptor(javax.swing.JLayeredPane.class.getMethod("getLayeredPaneAbove", new Class[] {java.awt.Component.class})); // NOI18N
-            methods[METHOD_getLayeredPaneAbove60].setDisplayName ( "" );
-            methods[METHOD_getListeners61] = new MethodDescriptor(javax.swing.JComponent.class.getMethod("getListeners", new Class[] {java.lang.Class.class})); // NOI18N
-            methods[METHOD_getListeners61].setDisplayName ( "" );
-            methods[METHOD_getLocation62] = new MethodDescriptor(javax.swing.JComponent.class.getMethod("getLocation", new Class[] {java.awt.Point.class})); // NOI18N
-            methods[METHOD_getLocation62].setDisplayName ( "" );
-            methods[METHOD_getMousePosition63] = new MethodDescriptor(java.awt.Container.class.getMethod("getMousePosition", new Class[] {boolean.class})); // NOI18N
-            methods[METHOD_getMousePosition63].setDisplayName ( "" );
-            methods[METHOD_getPopupLocation64] = new MethodDescriptor(javax.swing.JComponent.class.getMethod("getPopupLocation", new Class[] {java.awt.event.MouseEvent.class})); // NOI18N
-            methods[METHOD_getPopupLocation64].setDisplayName ( "" );
-            methods[METHOD_getPosition65] = new MethodDescriptor(javax.swing.JLayeredPane.class.getMethod("getPosition", new Class[] {java.awt.Component.class})); // NOI18N
-            methods[METHOD_getPosition65].setDisplayName ( "" );
-            methods[METHOD_getPropertyChangeListeners66] = new MethodDescriptor(java.awt.Component.class.getMethod("getPropertyChangeListeners", new Class[] {java.lang.String.class})); // NOI18N
-            methods[METHOD_getPropertyChangeListeners66].setDisplayName ( "" );
-            methods[METHOD_getSize67] = new MethodDescriptor(javax.swing.JComponent.class.getMethod("getSize", new Class[] {java.awt.Dimension.class})); // NOI18N
-            methods[METHOD_getSize67].setDisplayName ( "" );
-            methods[METHOD_getToolTipLocation68] = new MethodDescriptor(javax.swing.JComponent.class.getMethod("getToolTipLocation", new Class[] {java.awt.event.MouseEvent.class})); // NOI18N
-            methods[METHOD_getToolTipLocation68].setDisplayName ( "" );
-            methods[METHOD_getToolTipText69] = new MethodDescriptor(javax.swing.JComponent.class.getMethod("getToolTipText", new Class[] {java.awt.event.MouseEvent.class})); // NOI18N
-            methods[METHOD_getToolTipText69].setDisplayName ( "" );
-            methods[METHOD_gotFocus70] = new MethodDescriptor(java.awt.Component.class.getMethod("gotFocus", new Class[] {java.awt.Event.class, java.lang.Object.class})); // NOI18N
-            methods[METHOD_gotFocus70].setDisplayName ( "" );
-            methods[METHOD_grabFocus71] = new MethodDescriptor(javax.swing.JComponent.class.getMethod("grabFocus", new Class[] {})); // NOI18N
-            methods[METHOD_grabFocus71].setDisplayName ( "" );
-            methods[METHOD_handleEvent72] = new MethodDescriptor(java.awt.Component.class.getMethod("handleEvent", new Class[] {java.awt.Event.class})); // NOI18N
-            methods[METHOD_handleEvent72].setDisplayName ( "" );
-            methods[METHOD_hasFocus73] = new MethodDescriptor(java.awt.Component.class.getMethod("hasFocus", new Class[] {})); // NOI18N
-            methods[METHOD_hasFocus73].setDisplayName ( "" );
-            methods[METHOD_hide74] = new MethodDescriptor(java.awt.Component.class.getMethod("hide", new Class[] {})); // NOI18N
-            methods[METHOD_hide74].setDisplayName ( "" );
-            methods[METHOD_highestLayer75] = new MethodDescriptor(javax.swing.JLayeredPane.class.getMethod("highestLayer", new Class[] {})); // NOI18N
-            methods[METHOD_highestLayer75].setDisplayName ( "" );
-            methods[METHOD_imageUpdate76] = new MethodDescriptor(java.awt.Component.class.getMethod("imageUpdate", new Class[] {java.awt.Image.class, int.class, int.class, int.class, int.class, int.class})); // NOI18N
-            methods[METHOD_imageUpdate76].setDisplayName ( "" );
-            methods[METHOD_initialize77] = new MethodDescriptor(squidpony.squidgrid.gui.swing.SwingPane.class.getMethod("initialize", new Class[] {int.class, int.class, int.class, int.class, java.awt.Font.class})); // NOI18N
-            methods[METHOD_initialize77].setDisplayName ( "" );
-            methods[METHOD_initialize78] = new MethodDescriptor(squidpony.squidgrid.gui.swing.SwingPane.class.getMethod("initialize", new Class[] {int.class, int.class, java.awt.Font.class})); // NOI18N
-            methods[METHOD_initialize78].setDisplayName ( "" );
-            methods[METHOD_insets79] = new MethodDescriptor(java.awt.Container.class.getMethod("insets", new Class[] {})); // NOI18N
-            methods[METHOD_insets79].setDisplayName ( "" );
-            methods[METHOD_inside80] = new MethodDescriptor(java.awt.Component.class.getMethod("inside", new Class[] {int.class, int.class})); // NOI18N
-            methods[METHOD_inside80].setDisplayName ( "" );
-            methods[METHOD_invalidate81] = new MethodDescriptor(java.awt.Container.class.getMethod("invalidate", new Class[] {})); // NOI18N
-            methods[METHOD_invalidate81].setDisplayName ( "" );
-            methods[METHOD_isAncestorOf82] = new MethodDescriptor(java.awt.Container.class.getMethod("isAncestorOf", new Class[] {java.awt.Component.class})); // NOI18N
-            methods[METHOD_isAncestorOf82].setDisplayName ( "" );
-            methods[METHOD_isFocusCycleRoot83] = new MethodDescriptor(java.awt.Container.class.getMethod("isFocusCycleRoot", new Class[] {java.awt.Container.class})); // NOI18N
-            methods[METHOD_isFocusCycleRoot83].setDisplayName ( "" );
-            methods[METHOD_isLightweightComponent84] = new MethodDescriptor(javax.swing.JComponent.class.getMethod("isLightweightComponent", new Class[] {java.awt.Component.class})); // NOI18N
-            methods[METHOD_isLightweightComponent84].setDisplayName ( "" );
-            methods[METHOD_keyDown85] = new MethodDescriptor(java.awt.Component.class.getMethod("keyDown", new Class[] {java.awt.Event.class, int.class})); // NOI18N
-            methods[METHOD_keyDown85].setDisplayName ( "" );
-            methods[METHOD_keyUp86] = new MethodDescriptor(java.awt.Component.class.getMethod("keyUp", new Class[] {java.awt.Event.class, int.class})); // NOI18N
-            methods[METHOD_keyUp86].setDisplayName ( "" );
-            methods[METHOD_layout87] = new MethodDescriptor(java.awt.Container.class.getMethod("layout", new Class[] {})); // NOI18N
-            methods[METHOD_layout87].setDisplayName ( "" );
-            methods[METHOD_list88] = new MethodDescriptor(java.awt.Component.class.getMethod("list", new Class[] {})); // NOI18N
-            methods[METHOD_list88].setDisplayName ( "" );
-            methods[METHOD_list89] = new MethodDescriptor(java.awt.Component.class.getMethod("list", new Class[] {java.io.PrintStream.class})); // NOI18N
-            methods[METHOD_list89].setDisplayName ( "" );
-            methods[METHOD_list90] = new MethodDescriptor(java.awt.Component.class.getMethod("list", new Class[] {java.io.PrintWriter.class})); // NOI18N
-            methods[METHOD_list90].setDisplayName ( "" );
-            methods[METHOD_list91] = new MethodDescriptor(java.awt.Container.class.getMethod("list", new Class[] {java.io.PrintStream.class, int.class})); // NOI18N
-            methods[METHOD_list91].setDisplayName ( "" );
-            methods[METHOD_list92] = new MethodDescriptor(java.awt.Container.class.getMethod("list", new Class[] {java.io.PrintWriter.class, int.class})); // NOI18N
-            methods[METHOD_list92].setDisplayName ( "" );
-            methods[METHOD_locate93] = new MethodDescriptor(java.awt.Container.class.getMethod("locate", new Class[] {int.class, int.class})); // NOI18N
-            methods[METHOD_locate93].setDisplayName ( "" );
-            methods[METHOD_location94] = new MethodDescriptor(java.awt.Component.class.getMethod("location", new Class[] {})); // NOI18N
-            methods[METHOD_location94].setDisplayName ( "" );
-            methods[METHOD_lostFocus95] = new MethodDescriptor(java.awt.Component.class.getMethod("lostFocus", new Class[] {java.awt.Event.class, java.lang.Object.class})); // NOI18N
-            methods[METHOD_lostFocus95].setDisplayName ( "" );
-            methods[METHOD_lowestLayer96] = new MethodDescriptor(javax.swing.JLayeredPane.class.getMethod("lowestLayer", new Class[] {})); // NOI18N
-            methods[METHOD_lowestLayer96].setDisplayName ( "" );
-            methods[METHOD_minimumSize97] = new MethodDescriptor(java.awt.Container.class.getMethod("minimumSize", new Class[] {})); // NOI18N
-            methods[METHOD_minimumSize97].setDisplayName ( "" );
-            methods[METHOD_mouseDown98] = new MethodDescriptor(java.awt.Component.class.getMethod("mouseDown", new Class[] {java.awt.Event.class, int.class, int.class})); // NOI18N
-            methods[METHOD_mouseDown98].setDisplayName ( "" );
-            methods[METHOD_mouseDrag99] = new MethodDescriptor(java.awt.Component.class.getMethod("mouseDrag", new Class[] {java.awt.Event.class, int.class, int.class})); // NOI18N
-            methods[METHOD_mouseDrag99].setDisplayName ( "" );
-            methods[METHOD_mouseEnter100] = new MethodDescriptor(java.awt.Component.class.getMethod("mouseEnter", new Class[] {java.awt.Event.class, int.class, int.class})); // NOI18N
-            methods[METHOD_mouseEnter100].setDisplayName ( "" );
-            methods[METHOD_mouseExit101] = new MethodDescriptor(java.awt.Component.class.getMethod("mouseExit", new Class[] {java.awt.Event.class, int.class, int.class})); // NOI18N
-            methods[METHOD_mouseExit101].setDisplayName ( "" );
-            methods[METHOD_mouseMove102] = new MethodDescriptor(java.awt.Component.class.getMethod("mouseMove", new Class[] {java.awt.Event.class, int.class, int.class})); // NOI18N
-            methods[METHOD_mouseMove102].setDisplayName ( "" );
-            methods[METHOD_mouseUp103] = new MethodDescriptor(java.awt.Component.class.getMethod("mouseUp", new Class[] {java.awt.Event.class, int.class, int.class})); // NOI18N
-            methods[METHOD_mouseUp103].setDisplayName ( "" );
-            methods[METHOD_move104] = new MethodDescriptor(java.awt.Component.class.getMethod("move", new Class[] {int.class, int.class})); // NOI18N
-            methods[METHOD_move104].setDisplayName ( "" );
-            methods[METHOD_moveToBack105] = new MethodDescriptor(javax.swing.JLayeredPane.class.getMethod("moveToBack", new Class[] {java.awt.Component.class})); // NOI18N
-            methods[METHOD_moveToBack105].setDisplayName ( "" );
-            methods[METHOD_moveToFront106] = new MethodDescriptor(javax.swing.JLayeredPane.class.getMethod("moveToFront", new Class[] {java.awt.Component.class})); // NOI18N
-            methods[METHOD_moveToFront106].setDisplayName ( "" );
-            methods[METHOD_nextFocus107] = new MethodDescriptor(java.awt.Component.class.getMethod("nextFocus", new Class[] {})); // NOI18N
-            methods[METHOD_nextFocus107].setDisplayName ( "" );
-            methods[METHOD_paint108] = new MethodDescriptor(javax.swing.JLayeredPane.class.getMethod("paint", new Class[] {java.awt.Graphics.class})); // NOI18N
-            methods[METHOD_paint108].setDisplayName ( "" );
-            methods[METHOD_paintAll109] = new MethodDescriptor(java.awt.Component.class.getMethod("paintAll", new Class[] {java.awt.Graphics.class})); // NOI18N
-            methods[METHOD_paintAll109].setDisplayName ( "" );
-            methods[METHOD_paintComponent110] = new MethodDescriptor(squidpony.squidgrid.gui.swing.SwingPane.class.getMethod("paintComponent", new Class[] {java.awt.Graphics.class})); // NOI18N
-            methods[METHOD_paintComponent110].setDisplayName ( "" );
-            methods[METHOD_paintComponents111] = new MethodDescriptor(java.awt.Container.class.getMethod("paintComponents", new Class[] {java.awt.Graphics.class})); // NOI18N
-            methods[METHOD_paintComponents111].setDisplayName ( "" );
-            methods[METHOD_paintImmediately112] = new MethodDescriptor(javax.swing.JComponent.class.getMethod("paintImmediately", new Class[] {int.class, int.class, int.class, int.class})); // NOI18N
-            methods[METHOD_paintImmediately112].setDisplayName ( "" );
-            methods[METHOD_paintImmediately113] = new MethodDescriptor(javax.swing.JComponent.class.getMethod("paintImmediately", new Class[] {java.awt.Rectangle.class})); // NOI18N
-            methods[METHOD_paintImmediately113].setDisplayName ( "" );
-            methods[METHOD_placeCharacter114] = new MethodDescriptor(squidpony.squidgrid.gui.swing.SwingPane.class.getMethod("placeCharacter", new Class[] {int.class, int.class, char.class})); // NOI18N
-            methods[METHOD_placeCharacter114].setDisplayName ( "" );
-            methods[METHOD_placeCharacter115] = new MethodDescriptor(squidpony.squidgrid.gui.swing.SwingPane.class.getMethod("placeCharacter", new Class[] {int.class, int.class, char.class, java.awt.Color.class, java.awt.Color.class})); // NOI18N
-            methods[METHOD_placeCharacter115].setDisplayName ( "" );
-            methods[METHOD_placeCharacter116] = new MethodDescriptor(squidpony.squidgrid.gui.swing.SwingPane.class.getMethod("placeCharacter", new Class[] {int.class, int.class, char.class, java.awt.Color.class})); // NOI18N
-            methods[METHOD_placeCharacter116].setDisplayName ( "" );
-            methods[METHOD_placeHorizontalString117] = new MethodDescriptor(squidpony.squidgrid.gui.swing.SwingPane.class.getMethod("placeHorizontalString", new Class[] {int.class, int.class, java.lang.String.class})); // NOI18N
-            methods[METHOD_placeHorizontalString117].setDisplayName ( "" );
-            methods[METHOD_placeHorizontalString118] = new MethodDescriptor(squidpony.squidgrid.gui.swing.SwingPane.class.getMethod("placeHorizontalString", new Class[] {int.class, int.class, java.lang.String.class, java.awt.Color.class, java.awt.Color.class})); // NOI18N
-            methods[METHOD_placeHorizontalString118].setDisplayName ( "" );
-            methods[METHOD_placeImage119] = new MethodDescriptor(squidpony.squidgrid.gui.swing.SwingPane.class.getMethod("placeImage", new Class[] {int.class, int.class, java.lang.String.class})); // NOI18N
-            methods[METHOD_placeImage119].setDisplayName ( "" );
-            methods[METHOD_placeImage120] = new MethodDescriptor(squidpony.squidgrid.gui.swing.SwingPane.class.getMethod("placeImage", new Class[] {int.class, int.class, java.lang.String.class, java.awt.Color.class})); // NOI18N
-            methods[METHOD_placeImage120].setDisplayName ( "" );
-            methods[METHOD_placeText121] = new MethodDescriptor(squidpony.squidgrid.gui.swing.SwingPane.class.getMethod("placeText", new Class[] {int.class, int.class, char[][].class})); // NOI18N
-            methods[METHOD_placeText121].setDisplayName ( "" );
-            methods[METHOD_placeText122] = new MethodDescriptor(squidpony.squidgrid.gui.swing.SwingPane.class.getMethod("placeText", new Class[] {int.class, int.class, char[][].class, java.awt.Color.class, java.awt.Color.class})); // NOI18N
-            methods[METHOD_placeText122].setDisplayName ( "" );
-            methods[METHOD_placeVerticalString123] = new MethodDescriptor(squidpony.squidgrid.gui.swing.SwingPane.class.getMethod("placeVerticalString", new Class[] {int.class, int.class, java.lang.String.class, java.awt.Color.class, java.awt.Color.class})); // NOI18N
-            methods[METHOD_placeVerticalString123].setDisplayName ( "" );
-            methods[METHOD_placeVerticalString124] = new MethodDescriptor(squidpony.squidgrid.gui.swing.SwingPane.class.getMethod("placeVerticalString", new Class[] {int.class, int.class, java.lang.String.class})); // NOI18N
-            methods[METHOD_placeVerticalString124].setDisplayName ( "" );
-            methods[METHOD_postEvent125] = new MethodDescriptor(java.awt.Component.class.getMethod("postEvent", new Class[] {java.awt.Event.class})); // NOI18N
-            methods[METHOD_postEvent125].setDisplayName ( "" );
-            methods[METHOD_preferredSize126] = new MethodDescriptor(java.awt.Container.class.getMethod("preferredSize", new Class[] {})); // NOI18N
-            methods[METHOD_preferredSize126].setDisplayName ( "" );
-            methods[METHOD_prepareImage127] = new MethodDescriptor(java.awt.Component.class.getMethod("prepareImage", new Class[] {java.awt.Image.class, java.awt.image.ImageObserver.class})); // NOI18N
-            methods[METHOD_prepareImage127].setDisplayName ( "" );
-            methods[METHOD_prepareImage128] = new MethodDescriptor(java.awt.Component.class.getMethod("prepareImage", new Class[] {java.awt.Image.class, int.class, int.class, java.awt.image.ImageObserver.class})); // NOI18N
-            methods[METHOD_prepareImage128].setDisplayName ( "" );
-            methods[METHOD_print129] = new MethodDescriptor(javax.swing.JComponent.class.getMethod("print", new Class[] {java.awt.Graphics.class})); // NOI18N
-            methods[METHOD_print129].setDisplayName ( "" );
-            methods[METHOD_printAll130] = new MethodDescriptor(javax.swing.JComponent.class.getMethod("printAll", new Class[] {java.awt.Graphics.class})); // NOI18N
-            methods[METHOD_printAll130].setDisplayName ( "" );
-            methods[METHOD_printComponents131] = new MethodDescriptor(java.awt.Container.class.getMethod("printComponents", new Class[] {java.awt.Graphics.class})); // NOI18N
-            methods[METHOD_printComponents131].setDisplayName ( "" );
-            methods[METHOD_putClientProperty132] = new MethodDescriptor(javax.swing.JComponent.class.getMethod("putClientProperty", new Class[] {java.lang.Object.class, java.lang.Object.class})); // NOI18N
-            methods[METHOD_putClientProperty132].setDisplayName ( "" );
-            methods[METHOD_putLayer133] = new MethodDescriptor(javax.swing.JLayeredPane.class.getMethod("putLayer", new Class[] {javax.swing.JComponent.class, int.class})); // NOI18N
-            methods[METHOD_putLayer133].setDisplayName ( "" );
-            methods[METHOD_refresh134] = new MethodDescriptor(squidpony.squidgrid.gui.swing.SwingPane.class.getMethod("refresh", new Class[] {})); // NOI18N
-            methods[METHOD_refresh134].setDisplayName ( "" );
-            methods[METHOD_registerKeyboardAction135] = new MethodDescriptor(javax.swing.JComponent.class.getMethod("registerKeyboardAction", new Class[] {java.awt.event.ActionListener.class, java.lang.String.class, javax.swing.KeyStroke.class, int.class})); // NOI18N
-            methods[METHOD_registerKeyboardAction135].setDisplayName ( "" );
-            methods[METHOD_registerKeyboardAction136] = new MethodDescriptor(javax.swing.JComponent.class.getMethod("registerKeyboardAction", new Class[] {java.awt.event.ActionListener.class, javax.swing.KeyStroke.class, int.class})); // NOI18N
-            methods[METHOD_registerKeyboardAction136].setDisplayName ( "" );
-            methods[METHOD_remove137] = new MethodDescriptor(java.awt.Component.class.getMethod("remove", new Class[] {java.awt.MenuComponent.class})); // NOI18N
-            methods[METHOD_remove137].setDisplayName ( "" );
-            methods[METHOD_remove138] = new MethodDescriptor(java.awt.Container.class.getMethod("remove", new Class[] {java.awt.Component.class})); // NOI18N
-            methods[METHOD_remove138].setDisplayName ( "" );
-            methods[METHOD_remove139] = new MethodDescriptor(javax.swing.JLayeredPane.class.getMethod("remove", new Class[] {int.class})); // NOI18N
-            methods[METHOD_remove139].setDisplayName ( "" );
-            methods[METHOD_removeAll140] = new MethodDescriptor(javax.swing.JLayeredPane.class.getMethod("removeAll", new Class[] {})); // NOI18N
-            methods[METHOD_removeAll140].setDisplayName ( "" );
-            methods[METHOD_removeNotify141] = new MethodDescriptor(javax.swing.JComponent.class.getMethod("removeNotify", new Class[] {})); // NOI18N
-            methods[METHOD_removeNotify141].setDisplayName ( "" );
-            methods[METHOD_removePropertyChangeListener142] = new MethodDescriptor(java.awt.Component.class.getMethod("removePropertyChangeListener", new Class[] {java.lang.String.class, java.beans.PropertyChangeListener.class})); // NOI18N
-            methods[METHOD_removePropertyChangeListener142].setDisplayName ( "" );
-            methods[METHOD_repaint143] = new MethodDescriptor(java.awt.Component.class.getMethod("repaint", new Class[] {})); // NOI18N
-            methods[METHOD_repaint143].setDisplayName ( "" );
-            methods[METHOD_repaint144] = new MethodDescriptor(java.awt.Component.class.getMethod("repaint", new Class[] {long.class})); // NOI18N
-            methods[METHOD_repaint144].setDisplayName ( "" );
-            methods[METHOD_repaint145] = new MethodDescriptor(java.awt.Component.class.getMethod("repaint", new Class[] {int.class, int.class, int.class, int.class})); // NOI18N
-            methods[METHOD_repaint145].setDisplayName ( "" );
-            methods[METHOD_repaint146] = new MethodDescriptor(javax.swing.JComponent.class.getMethod("repaint", new Class[] {long.class, int.class, int.class, int.class, int.class})); // NOI18N
-            methods[METHOD_repaint146].setDisplayName ( "" );
-            methods[METHOD_repaint147] = new MethodDescriptor(javax.swing.JComponent.class.getMethod("repaint", new Class[] {java.awt.Rectangle.class})); // NOI18N
-            methods[METHOD_repaint147].setDisplayName ( "" );
-            methods[METHOD_requestDefaultFocus148] = new MethodDescriptor(javax.swing.JComponent.class.getMethod("requestDefaultFocus", new Class[] {})); // NOI18N
-            methods[METHOD_requestDefaultFocus148].setDisplayName ( "" );
-            methods[METHOD_requestFocus149] = new MethodDescriptor(javax.swing.JComponent.class.getMethod("requestFocus", new Class[] {})); // NOI18N
-            methods[METHOD_requestFocus149].setDisplayName ( "" );
-            methods[METHOD_requestFocus150] = new MethodDescriptor(javax.swing.JComponent.class.getMethod("requestFocus", new Class[] {boolean.class})); // NOI18N
-            methods[METHOD_requestFocus150].setDisplayName ( "" );
-            methods[METHOD_requestFocusInWindow151] = new MethodDescriptor(javax.swing.JComponent.class.getMethod("requestFocusInWindow", new Class[] {})); // NOI18N
-            methods[METHOD_requestFocusInWindow151].setDisplayName ( "" );
-            methods[METHOD_resetKeyboardActions152] = new MethodDescriptor(javax.swing.JComponent.class.getMethod("resetKeyboardActions", new Class[] {})); // NOI18N
-            methods[METHOD_resetKeyboardActions152].setDisplayName ( "" );
-            methods[METHOD_reshape153] = new MethodDescriptor(javax.swing.JComponent.class.getMethod("reshape", new Class[] {int.class, int.class, int.class, int.class})); // NOI18N
-            methods[METHOD_reshape153].setDisplayName ( "" );
-            methods[METHOD_resize154] = new MethodDescriptor(java.awt.Component.class.getMethod("resize", new Class[] {int.class, int.class})); // NOI18N
-            methods[METHOD_resize154].setDisplayName ( "" );
-            methods[METHOD_resize155] = new MethodDescriptor(java.awt.Component.class.getMethod("resize", new Class[] {java.awt.Dimension.class})); // NOI18N
-            methods[METHOD_resize155].setDisplayName ( "" );
-            methods[METHOD_revalidate156] = new MethodDescriptor(javax.swing.JComponent.class.getMethod("revalidate", new Class[] {})); // NOI18N
-            methods[METHOD_revalidate156].setDisplayName ( "" );
-            methods[METHOD_scrollRectToVisible157] = new MethodDescriptor(javax.swing.JComponent.class.getMethod("scrollRectToVisible", new Class[] {java.awt.Rectangle.class})); // NOI18N
-            methods[METHOD_scrollRectToVisible157].setDisplayName ( "" );
-            methods[METHOD_setBounds158] = new MethodDescriptor(java.awt.Component.class.getMethod("setBounds", new Class[] {int.class, int.class, int.class, int.class})); // NOI18N
-            methods[METHOD_setBounds158].setDisplayName ( "" );
-            methods[METHOD_setComponentZOrder159] = new MethodDescriptor(java.awt.Container.class.getMethod("setComponentZOrder", new Class[] {java.awt.Component.class, int.class})); // NOI18N
-            methods[METHOD_setComponentZOrder159].setDisplayName ( "" );
-            methods[METHOD_setDefaultLocale160] = new MethodDescriptor(javax.swing.JComponent.class.getMethod("setDefaultLocale", new Class[] {java.util.Locale.class})); // NOI18N
-            methods[METHOD_setDefaultLocale160].setDisplayName ( "" );
-            methods[METHOD_setLayer161] = new MethodDescriptor(javax.swing.JLayeredPane.class.getMethod("setLayer", new Class[] {java.awt.Component.class, int.class})); // NOI18N
-            methods[METHOD_setLayer161].setDisplayName ( "" );
-            methods[METHOD_setLayer162] = new MethodDescriptor(javax.swing.JLayeredPane.class.getMethod("setLayer", new Class[] {java.awt.Component.class, int.class, int.class})); // NOI18N
-            methods[METHOD_setLayer162].setDisplayName ( "" );
-            methods[METHOD_setPosition163] = new MethodDescriptor(javax.swing.JLayeredPane.class.getMethod("setPosition", new Class[] {java.awt.Component.class, int.class})); // NOI18N
-            methods[METHOD_setPosition163].setDisplayName ( "" );
-            methods[METHOD_show164] = new MethodDescriptor(java.awt.Component.class.getMethod("show", new Class[] {})); // NOI18N
-            methods[METHOD_show164].setDisplayName ( "" );
-            methods[METHOD_show165] = new MethodDescriptor(java.awt.Component.class.getMethod("show", new Class[] {boolean.class})); // NOI18N
-            methods[METHOD_show165].setDisplayName ( "" );
-            methods[METHOD_size166] = new MethodDescriptor(java.awt.Component.class.getMethod("size", new Class[] {})); // NOI18N
-            methods[METHOD_size166].setDisplayName ( "" );
-            methods[METHOD_slide167] = new MethodDescriptor(squidpony.squidgrid.gui.swing.SwingPane.class.getMethod("slide", new Class[] {java.awt.Point.class, java.awt.Point.class})); // NOI18N
-            methods[METHOD_slide167].setDisplayName ( "" );
-            methods[METHOD_slide168] = new MethodDescriptor(squidpony.squidgrid.gui.swing.SwingPane.class.getMethod("slide", new Class[] {java.awt.Point.class, squidpony.squidgrid.util.Direction.class})); // NOI18N
-            methods[METHOD_slide168].setDisplayName ( "" );
-            methods[METHOD_slide169] = new MethodDescriptor(squidpony.squidgrid.gui.swing.SwingPane.class.getMethod("slide", new Class[] {java.awt.Point.class, java.awt.Point.class, int.class})); // NOI18N
-            methods[METHOD_slide169].setDisplayName ( "" );
-            methods[METHOD_toString170] = new MethodDescriptor(java.awt.Component.class.getMethod("toString", new Class[] {})); // NOI18N
-            methods[METHOD_toString170].setDisplayName ( "" );
-            methods[METHOD_transferFocus171] = new MethodDescriptor(java.awt.Component.class.getMethod("transferFocus", new Class[] {})); // NOI18N
-            methods[METHOD_transferFocus171].setDisplayName ( "" );
-            methods[METHOD_transferFocusBackward172] = new MethodDescriptor(java.awt.Component.class.getMethod("transferFocusBackward", new Class[] {})); // NOI18N
-            methods[METHOD_transferFocusBackward172].setDisplayName ( "" );
-            methods[METHOD_transferFocusDownCycle173] = new MethodDescriptor(java.awt.Container.class.getMethod("transferFocusDownCycle", new Class[] {})); // NOI18N
-            methods[METHOD_transferFocusDownCycle173].setDisplayName ( "" );
-            methods[METHOD_transferFocusUpCycle174] = new MethodDescriptor(java.awt.Component.class.getMethod("transferFocusUpCycle", new Class[] {})); // NOI18N
-            methods[METHOD_transferFocusUpCycle174].setDisplayName ( "" );
-            methods[METHOD_unregisterKeyboardAction175] = new MethodDescriptor(javax.swing.JComponent.class.getMethod("unregisterKeyboardAction", new Class[] {javax.swing.KeyStroke.class})); // NOI18N
-            methods[METHOD_unregisterKeyboardAction175].setDisplayName ( "" );
-            methods[METHOD_update176] = new MethodDescriptor(javax.swing.JComponent.class.getMethod("update", new Class[] {java.awt.Graphics.class})); // NOI18N
-            methods[METHOD_update176].setDisplayName ( "" );
-            methods[METHOD_updateUI177] = new MethodDescriptor(javax.swing.JComponent.class.getMethod("updateUI", new Class[] {})); // NOI18N
-            methods[METHOD_updateUI177].setDisplayName ( "" );
-            methods[METHOD_validate178] = new MethodDescriptor(java.awt.Container.class.getMethod("validate", new Class[] {})); // NOI18N
-            methods[METHOD_validate178].setDisplayName ( "" );
-            methods[METHOD_waitForAnimations179] = new MethodDescriptor(squidpony.squidgrid.gui.swing.SwingPane.class.getMethod("waitForAnimations", new Class[] {})); // NOI18N
-            methods[METHOD_waitForAnimations179].setDisplayName ( "" );
-            methods[METHOD_wiggle180] = new MethodDescriptor(squidpony.squidgrid.gui.swing.SwingPane.class.getMethod("wiggle", new Class[] {java.awt.Point.class})); // NOI18N
-            methods[METHOD_wiggle180].setDisplayName ( "" );
-            methods[METHOD_willFit181] = new MethodDescriptor(squidpony.squidgrid.gui.swing.SwingPane.class.getMethod("willFit", new Class[] {char.class})); // NOI18N
-            methods[METHOD_willFit181].setDisplayName ( "" );
-        }
-        catch( Exception e) {}//GEN-HEADEREND:Methods
-
-        // Here you can add code for customizing the methods array.
-        
-        return methods;     }//GEN-LAST:Methods
-    private static java.awt.Image iconColor16 = null;//GEN-BEGIN:IconsDef
-    private static java.awt.Image iconColor32 = null;
-    private static java.awt.Image iconMono16 = null;
-    private static java.awt.Image iconMono32 = null;//GEN-END:IconsDef
-    private static String iconNameC16 = null;//GEN-BEGIN:Icons
-    private static String iconNameC32 = null;
-    private static String iconNameM16 = null;
-    private static String iconNameM32 = null;//GEN-END:Icons
-    private static final int defaultPropertyIndex = -1;//GEN-BEGIN:Idx
-    private static final int defaultEventIndex = -1;//GEN-END:Idx
-
-//GEN-FIRST:Superclass
-    // Here you can add code for customizing the Superclass BeanInfo.
-//GEN-LAST:Superclass
-    /**
-     * Gets the bean's
-     * BeanDescriptors.
-     *
-     * @return BeanDescriptor describing the editable properties of this bean.
-     * May return null if the information should be obtained by automatic
-     * analysis.
-     */
-    @Override
-    public BeanDescriptor getBeanDescriptor() {
-        return getBdescriptor();
-    }
-
-    /**
-     * Gets the bean's
-     * PropertyDescriptors.
-     *
-     * @return An array of PropertyDescriptors describing the editable
-     * properties supported by this bean. May return null if the information
-     * should be obtained by automatic analysis. 

If a property is indexed, - * then its entry in the result array will belong to the - * IndexedPropertyDescriptor subclass of PropertyDescriptor. A client of - * getPropertyDescriptors can use "instanceof" to check if a given - * PropertyDescriptor is an IndexedPropertyDescriptor. - */ - @Override - public PropertyDescriptor[] getPropertyDescriptors() { - return getPdescriptor(); - } - - /** - * Gets the bean's - * EventSetDescriptors. - * - * @return An array of EventSetDescriptors describing the kinds of events - * fired by this bean. May return null if the information should be obtained - * by automatic analysis. - */ - @Override - public EventSetDescriptor[] getEventSetDescriptors() { - return getEdescriptor(); - } - - /** - * Gets the bean's - * MethodDescriptors. - * - * @return An array of MethodDescriptors describing the methods implemented - * by this bean. May return null if the information should be obtained by - * automatic analysis. - */ - @Override - public MethodDescriptor[] getMethodDescriptors() { - return getMdescriptor(); - } - - /** - * A bean may have a "default" property that is the property that will - * mostly commonly be initially chosen for update by human's who are - * customizing the bean. - * - * @return Index of default property in the PropertyDescriptor array - * returned by getPropertyDescriptors.

Returns -1 if there is no default - * property. - */ - @Override - public int getDefaultPropertyIndex() { - return defaultPropertyIndex; - } - - /** - * A bean may have a "default" event that is the event that will mostly - * commonly be used by human's when using the bean. - * - * @return Index of default event in the EventSetDescriptor array returned - * by getEventSetDescriptors.

Returns -1 if there is no default event. - */ - @Override - public int getDefaultEventIndex() { - return defaultEventIndex; - } - - /** - * This method returns an image object that can be used to represent the - * bean in toolboxes, toolbars, etc. Icon images will typically be GIFs, but - * may in future include other formats.

Beans aren't required to provide - * icons and may return null from this method.

There are four possible - * flavors of icons (16x16 color, 32x32 color, 16x16 mono, 32x32 mono). If a - * bean choses to only support a single icon we recommend supporting 16x16 - * color.

We recommend that icons have a "transparent" background so - * they can be rendered onto an existing background. - * - * @param iconKind The kind of icon requested. This should be one of the - * constant values ICON_COLOR_16x16, ICON_COLOR_32x32, ICON_MONO_16x16, or - * ICON_MONO_32x32. - * @return An image object representing the requested icon. May return null - * if no suitable icon is available. - */ - @Override - public java.awt.Image getIcon(int iconKind) { - switch (iconKind) { - case ICON_COLOR_16x16: - if (iconNameC16 == null) { - return null; - } else { - if (iconColor16 == null) { - iconColor16 = loadImage(iconNameC16); - } - return iconColor16; - } - case ICON_COLOR_32x32: - if (iconNameC32 == null) { - return null; - } else { - if (iconColor32 == null) { - iconColor32 = loadImage(iconNameC32); - } - return iconColor32; - } - case ICON_MONO_16x16: - if (iconNameM16 == null) { - return null; - } else { - if (iconMono16 == null) { - iconMono16 = loadImage(iconNameM16); - } - return iconMono16; - } - case ICON_MONO_32x32: - if (iconNameM32 == null) { - return null; - } else { - if (iconMono32 == null) { - iconMono32 = loadImage(iconNameM32); - } - return iconMono32; - } - default: - return null; - } - } -} diff --git a/src/main/java/squidpony/squidgrid/gui/swing/animation/Animation.java b/src/main/java/squidpony/squidgrid/gui/swing/animation/Animation.java index c70a4181ee..b28b85af79 100644 --- a/src/main/java/squidpony/squidgrid/gui/swing/animation/Animation.java +++ b/src/main/java/squidpony/squidgrid/gui/swing/animation/Animation.java @@ -8,16 +8,19 @@ /** * Controls animations of images. Intended to be used with a Timer to activate * the animation frames. - * - * The component for the animation must be set before the animation will function properly. - * All coordinates will be relative to the coordinate plane of the provided component. * - * @author Eben Howard - http://squidpony.com + * The component for the animation must be set before the animation will + * function properly. All coordinates will be relative to the coordinate plane + * of the provided component. + * + * @author Eben Howard - http://squidpony.com - howard@squidpony.com */ public interface Animation extends ActionListener { + /** - * Returns true if the component should continue to be allowed to animate. Animations on a loop - * will always return true so some outside mechanism must decide when to terminate them. + * Returns true if the component should continue to be allowed to animate. + * Animations on a loop will always return true so some outside mechanism + * must decide when to terminate them. * * @return */ @@ -25,27 +28,27 @@ public interface Animation extends ActionListener { /** * Returns the number of milliseconds desired between frames of animation. - * - * @return + * + * @return */ public int getDelay(); /** - * Returns the static image associated with this animation. Will typically be - * the ending image, but this may vary based on the animation style. - * - * This method is intended to be called when converting an animation into a static - * image. - * - * @return + * Returns the static image associated with this animation. Will typically + * be the ending image, but this may vary based on the animation style. + * + * This method is intended to be called when converting an animation into a + * static image. + * + * @return */ public BufferedImage getImage(); /** * Sets the Component in which this animation will take place. This must be * set for the animation to function. - * - * @param component + * + * @param component */ public void setComponent(JComponent component); @@ -56,8 +59,8 @@ public interface Animation extends ActionListener { /** * Returns the coordinate of the top left corner of the animation. - * - * @return + * + * @return */ public Point getLocation(); } \ No newline at end of file diff --git a/src/main/java/squidpony/squidgrid/gui/swing/animation/AnimationManager.java b/src/main/java/squidpony/squidgrid/gui/swing/animation/AnimationManager.java index 59a4682015..e4e8517d77 100644 --- a/src/main/java/squidpony/squidgrid/gui/swing/animation/AnimationManager.java +++ b/src/main/java/squidpony/squidgrid/gui/swing/animation/AnimationManager.java @@ -11,7 +11,7 @@ * This class manages a collection of animations and handles update drawing to * the provided BufferedImage. * - * @author Eben Howard - http://squidpony.com + * @author Eben Howard - http://squidpony.com - howard@squidpony.com */ public class AnimationManager implements Runnable { diff --git a/src/main/java/squidpony/squidgrid/gui/swing/animation/BumpAnimation.java b/src/main/java/squidpony/squidgrid/gui/swing/animation/BumpAnimation.java index 72ab75a287..0a5d5a4636 100644 --- a/src/main/java/squidpony/squidgrid/gui/swing/animation/BumpAnimation.java +++ b/src/main/java/squidpony/squidgrid/gui/swing/animation/BumpAnimation.java @@ -10,37 +10,39 @@ import javax.swing.JLabel; import javax.swing.JLayeredPane; import squidpony.squidmath.Bresenham; -import squidpony.squidmath.Point3D; /** * Animates an object moving smoothly in a direction and then bouncing back. * - * @author Eben Howard http://squidpony.com + * @author Eben Howard - http://squidpony.com - howard@squidpony.com */ public class BumpAnimation implements Animation { - private Queue moves; + + private Queue moves; private JComponent component; private JLabel label; private Point start; /** - * Creates a bump animation that will travel one cell in the given direction. - * + * Creates a bump animation that will travel one cell in the given + * direction. + * * @param image * @param start * @param cellSize - * @param direction + * @param direction */ public BumpAnimation(BufferedImage image, Point start, Dimension cellSize, Point direction) { this(image, start, new Point(start.x + direction.x * cellSize.width, start.y + direction.y * cellSize.height)); } /** - * Creates a bump animation that will travel from the start to the end point and then back. - * + * Creates a bump animation that will travel from the start to the end point + * and then back. + * * @param image * @param start - * @param end + * @param end */ public BumpAnimation(BufferedImage image, Point start, Point end) { this.start = start; diff --git a/src/main/java/squidpony/squidgrid/gui/swing/animation/SlideAnimation.java b/src/main/java/squidpony/squidgrid/gui/swing/animation/SlideAnimation.java index 55b5407fc5..fc44049c66 100644 --- a/src/main/java/squidpony/squidgrid/gui/swing/animation/SlideAnimation.java +++ b/src/main/java/squidpony/squidgrid/gui/swing/animation/SlideAnimation.java @@ -10,15 +10,14 @@ import javax.swing.JLabel; import javax.swing.JLayeredPane; import squidpony.squidmath.Bresenham; -import squidpony.squidmath.Point3D; /** * This class animates an image sliding directly from one point to another. * - * @author Eben Howard - http://squidpony.com + * @author Eben Howard - http://squidpony.com - howard@squidpony.com */ public class SlideAnimation implements Animation { - private Queue moves; + private Queue moves; private JComponent component; private JLabel label; private int delay; diff --git a/src/main/java/squidpony/squidgrid/gui/swing/animation/WiggleAnimation.java b/src/main/java/squidpony/squidgrid/gui/swing/animation/WiggleAnimation.java index ac1f616ffc..2c175fa20e 100644 --- a/src/main/java/squidpony/squidgrid/gui/swing/animation/WiggleAnimation.java +++ b/src/main/java/squidpony/squidgrid/gui/swing/animation/WiggleAnimation.java @@ -12,14 +12,15 @@ import javax.swing.JLayeredPane; /** - * This class animates an object by causing it to wiggle semi-randomly without straying - * too far from it's original point. - * + * This class animates an object by causing it to wiggle semi-randomly without + * straying too far from it's original point. + * * This can be set to last only a certain amount of time, or be continuous. * - * @author Eben Howard http://squidpony.com + * @author Eben Howard - http://squidpony.com - howard@squidpony.com */ public class WiggleAnimation implements Animation { + private long stopTime = 0;//0 indicates that it is continuous private Point origin;//starting point private Point2D.Double location = new Point2D.Double(0, 0); diff --git a/src/main/java/squidpony/squidgrid/util/Direction.java b/src/main/java/squidpony/squidgrid/util/Direction.java index 551ebb1a19..d0ae519360 100644 --- a/src/main/java/squidpony/squidgrid/util/Direction.java +++ b/src/main/java/squidpony/squidgrid/util/Direction.java @@ -6,7 +6,7 @@ * * The grid referenced has x positive to the right and y positive downwards. * - * @author Eben Howard - http://squidpony.com + * @author Eben Howard - http://squidpony.com - howard@squidpony.com */ public enum Direction { @@ -69,6 +69,95 @@ static public Direction getDirection(int x, int y) { } } + /** + * Returns the Direction one step clockwise including diagonals. + * + * @param dir + * @return + */ + public Direction clockwise() { + switch (this) { + case UP: + return UP_RIGHT; + case DOWN: + return DOWN_LEFT; + case LEFT: + return UP_LEFT; + case RIGHT: + return DOWN_RIGHT; + case UP_LEFT: + return UP; + case UP_RIGHT: + return RIGHT; + case DOWN_LEFT: + return LEFT; + case DOWN_RIGHT: + return DOWN; + case NONE: + default: + return NONE; + } + } + + /** + * Returns the Direction one step counterclockwise including diagonals. + * + * @param dir + * @return + */ + public Direction counterClockwise() { + switch (this) { + case UP: + return UP_LEFT; + case DOWN: + return DOWN_RIGHT; + case LEFT: + return DOWN_LEFT; + case RIGHT: + return UP_RIGHT; + case UP_LEFT: + return LEFT; + case UP_RIGHT: + return UP; + case DOWN_LEFT: + return DOWN; + case DOWN_RIGHT: + return RIGHT; + case NONE: + default: + return NONE; + } + } + + /** + * Returns the direction directly opposite of this one. + * + * @return + */ + public Direction opposite() { + switch (this) { + case UP: + return DOWN; + case DOWN: + return UP; + case LEFT: + return RIGHT; + case RIGHT: + return LEFT; + case UP_LEFT: + return DOWN_RIGHT; + case UP_RIGHT: + return DOWN_LEFT; + case DOWN_LEFT: + return UP_RIGHT; + case DOWN_RIGHT: + return UP_LEFT; + case NONE: + default: + return NONE; + } + } + private Direction(int x, int y) { this.deltaX = x; this.deltaY = y; diff --git a/src/main/java/squidpony/squidmath/Bresenham.java b/src/main/java/squidpony/squidmath/Bresenham.java index 507a253b90..3b09b9e44b 100644 --- a/src/main/java/squidpony/squidmath/Bresenham.java +++ b/src/main/java/squidpony/squidmath/Bresenham.java @@ -5,7 +5,9 @@ import java.util.Queue; /** - * @author Eben Howard - http://squidpony.com + * Provides a means to generate Bresenham lines in 2D and 3D. + * + * @author Eben Howard - http://squidpony.com - howard@squidpony.com * @author Lewis Potter */ public class Bresenham { @@ -16,14 +18,6 @@ public class Bresenham { private Bresenham() { } - /** - * Returns 0 for 0, -1 for negative parameters and 1 for positive - * parameters. - */ - private static int zsgn(int a) { - return ((a < 0) ? -1 : (a > 0) ? 1 : 0); - } - /** * Generates a 2D Bresenham line between two points. * @@ -31,7 +25,7 @@ private static int zsgn(int a) { * @param b * @return */ - public static Queue line2D(Point a, Point b) { + public static Queue line2D(Point a, Point b) { return line2D(a.x, a.y, b.x, b.y); } @@ -44,8 +38,13 @@ public static Queue line2D(Point a, Point b) { * @param endY * @return */ - public static Queue line2D(int startX, int startY, int endX, int endY) { - return line3D(startX, startY, 0, endX, endY, 0); + public static Queue line2D(int startX, int startY, int endX, int endY) { + Queue line = new LinkedList<>(); + Queue found = line3D(startX, startY, 0, endX, endY, 0); + while (!found.isEmpty()) { + line.offer(found.poll()); + } + return line; } /** @@ -62,107 +61,102 @@ public static Queue line3D(Point3D a, Point3D b) { /** * Generates a 3D Bresenham line between the given coordinates. * - * @param x1 - * @param y1 - * @param z1 - * @param x2 - * @param y2 - * @param z2 + * @param startx + * @param starty + * @param startz + * @param endx + * @param endy + * @param endz * @return */ - public static Queue line3D(int x1, int y1, int z1, int x2, int y2, int z2) { - Queue result = new LinkedList(); - - int xd, yd, zd; - int x, y, z; - int ax, ay, az; - int sx, sy, sz; - int dx, dy, dz; + public static Queue line3D(int startx, int starty, int startz, int endx, int endy, int endz) { + Queue result = new LinkedList<>(); - dx = x2 - x1; - dy = y2 - y1; - dz = z2 - z1; + int dx = endx - startx; + int dy = endy - starty; + int dz = endz - startz; - ax = Math.abs(dx) << 1; - ay = Math.abs(dy) << 1; - az = Math.abs(dz) << 1; + int ax = Math.abs(dx) << 1; + int ay = Math.abs(dy) << 1; + int az = Math.abs(dz) << 1; - sx = zsgn(dx); - sy = zsgn(dy); - sz = zsgn(dz); + int signx = (int) Math.signum(dx); + int signy = (int) Math.signum(dy); + int signz = (int) Math.signum(dz); - x = x1; - y = y1; - z = z1; + int x = startx; + int y = starty; + int z = startz; + int deltax, deltay, deltaz; if (ax >= Math.max(ay, az)) /* x dominant */ { - yd = ay - (ax >> 1); - zd = az - (ax >> 1); - for (;;) { + deltay = ay - (ax >> 1); + deltaz = az - (ax >> 1); + while (true) { result.offer(new Point3D(x, y, z)); - if (x == x2) { + if (x == endx) { return result; } - if (yd >= 0) { - y += sy; - yd -= ax; + if (deltay >= 0) { + y += signy; + deltay -= ax; } - if (zd >= 0) { - z += sz; - zd -= ax; + if (deltaz >= 0) { + z += signz; + deltaz -= ax; } - x += sx; - yd += ay; - zd += az; + x += signx; + deltay += ay; + deltaz += az; } } else if (ay >= Math.max(ax, az)) /* y dominant */ { - xd = ax - (ay >> 1); - zd = az - (ay >> 1); - for (;;) { + deltax = ax - (ay >> 1); + deltaz = az - (ay >> 1); + while (true) { result.offer(new Point3D(x, y, z)); - if (y == y2) { + if (y == endy) { return result; } - if (xd >= 0) { - x += sx; - xd -= ay; + if (deltax >= 0) { + x += signx; + deltax -= ay; } - if (zd >= 0) { - z += sz; - zd -= ay; + if (deltaz >= 0) { + z += signz; + deltaz -= ay; } - y += sy; - xd += ax; - zd += az; + y += signy; + deltax += ax; + deltaz += az; } } else if (az >= Math.max(ax, ay)) /* z dominant */ { - xd = ax - (az >> 1); - yd = ay - (az >> 1); - for (;;) { + deltax = ax - (az >> 1); + deltay = ay - (az >> 1); + while (true) { result.offer(new Point3D(x, y, z)); - if (z == z2) { + if (z == endz) { return result; } - if (xd >= 0) { - x += sx; - xd -= az; + if (deltax >= 0) { + x += signx; + deltax -= az; } - if (yd >= 0) { - y += sy; - yd -= az; + if (deltay >= 0) { + y += signy; + deltay -= az; } - z += sz; - xd += ax; - yd += ay; + z += signz; + deltax += ax; + deltay += ay; } } return result; diff --git a/src/main/java/squidpony/squidmath/Elias.java b/src/main/java/squidpony/squidmath/Elias.java new file mode 100644 index 0000000000..15606fd40b --- /dev/null +++ b/src/main/java/squidpony/squidmath/Elias.java @@ -0,0 +1,179 @@ +package squidpony.squidmath; + +import java.awt.Point; +import java.util.LinkedList; +import java.util.List; +import squidpony.annotation.Beta; + +/** + * Contains methods to draw antialiased lines based on floating point + * coordinates. + * + * Because of the way this line is calculated, endpoints may be swapped and + * therefore the list may not be in start-to-end order. + * + * Based on work by Hugo Elias at + * http://freespace.virgin.net/hugo.elias/graphics/x_wuline.htm which is in turn + * base on work by Wu. + * + * @author Eben Howard - http://squidpony.com - howard@squidpony.com + */ +@Beta +public class Elias { + + static private List path; + static private float[][] lightMap; + static private int width, height; + + private Elias() { + } + + public static float[][] lightMap(double startx, double starty, double endx, double endy) { + line(startx, starty, endx, endy); + return lightMap; + } + + /** + * Gets the line between the two points. + * + * @param startx + * @param starty + * @param endx + * @param endy + * @return + */ + public static List line(double startx, double starty, double endx, double endy) { + path = new LinkedList<>(); + width = (int) (Math.max(startx, endx) + 1); + height = (int) (Math.max(starty, endy) + 1); + lightMap = new float[width][height]; + runLine(startx, starty, endx, endy); + return path; + } + + /** + * Marks the location as having the visibility given. + * + * @param x + * @param y + * @param c + */ + private static void mark(double x, double y, double c) { + //check bounds overflow from antialiasing + if (x >= 0 && x < width && y >= 0 && y < height) { + path.add(new Point((int) x, (int) y)); + lightMap[(int) x][(int) y] = (float) c; + } + } + + private static double trunc(double x) { + if (x < 0) { + return Math.ceil(x); + } else { + return Math.floor(x); + } + } + + private static double frac(double x) { + return x - trunc(x); + } + + private static double invfrac(double x) { + return 1 - frac(x); + } + + private static void runLine(double startx, double starty, double endx, double endy) { + double x1 = startx, y1 = starty, x2 = endx, y2 = endy; + double grad, xd, yd, length, xm, ym, xgap, ygap, xend, yend, xf, yf, brightness1, brightness2; + int x, y, ix1, ix2, iy1, iy2; + boolean shallow = false; + + xd = x2 - x1; + yd = y2 - y1; + + if (Math.abs(xd) > Math.abs(yd)) { + shallow = true; + } + + if (!shallow) { + double temp = x1; + x1 = y1; + y1 = temp; + temp = x2; + x2 = y2; + y2 = temp; + xd = x2 - x1; + yd = y2 - y1; + } + if (x1 > x2) { + double temp = x1; + x1 = x2; + x2 = temp; + temp = y1; + y1 = y2; + y2 = temp; + xd = x2 - x1; + yd = y2 - y1; + } + + grad = yd / xd; + + //add the first end point + xend = trunc(x1 + .5); + yend = y1 + grad * (xend - x1); + + xgap = invfrac(x1 + .5); + + ix1 = (int) xend; + iy1 = (int) yend; + + brightness1 = invfrac(yend) * xgap; + brightness2 = frac(yend) * xgap; + + if (shallow) { + mark(ix1, iy1, brightness1); + mark(ix1, iy1 + 1, brightness2); + } else { + mark(iy1, ix1, brightness1); + mark(iy1 + 1, ix1, brightness2); + } + + yf = yend + grad; + + //add the second end point + xend = trunc(x2 + .5); + yend = y2 + grad * (xend - x2); + + xgap = invfrac(x2 - .5); + + ix2 = (int) xend; + iy2 = (int) yend; + + brightness1 = invfrac(yend) * xgap; + brightness2 = frac(yend) * xgap; + + if (shallow) { + mark(ix2, iy2, brightness1); + mark(ix2, iy2 + 1, brightness2); + } else { + mark(iy2, ix2, brightness1); + mark(iy2 + 1, ix2, brightness2); + } + + //add the in-between points + for (x = ix1 + 1; x < ix2; x++) { + brightness1 = invfrac(yf); + brightness2 = frac(yf); + + if (shallow) { + mark(x, (int) yf, brightness1); + mark(x, (int) yf + 1, brightness2); + } else { + mark((int) yf, x, brightness1); + mark((int) yf + 1, x, brightness2); + } + + yf += grad; + } + } +} diff --git a/src/main/java/squidpony/squidmath/Point3D.java b/src/main/java/squidpony/squidmath/Point3D.java index de75e0ee11..bdb179e890 100644 --- a/src/main/java/squidpony/squidmath/Point3D.java +++ b/src/main/java/squidpony/squidmath/Point3D.java @@ -6,7 +6,7 @@ * Generic three dimensional coordinate class. * * @author Lewis Potter - * @author Eben Howard - http://squidpony.com + * @author Eben Howard - http://squidpony.com - howard@squidpony.com */ public class Point3D extends Point { public int z; diff --git a/src/main/java/squidpony/squidmath/RNG.java b/src/main/java/squidpony/squidmath/RNG.java index 11eecd9d26..a58989a914 100644 --- a/src/main/java/squidpony/squidmath/RNG.java +++ b/src/main/java/squidpony/squidmath/RNG.java @@ -1,15 +1,193 @@ package squidpony.squidmath; +import java.security.SecureRandom; import java.util.Random; +import java.util.concurrent.locks.ReentrantLock; /** * Customized extension of Random to allow for common roguelike operations. * + * Uses the Mersenne Twister algorithm to provide superior results. Because of + * the seed requirements for the MT, the seed setting methods and constructors + * that take a long do not set the seed. The methods that use a byte[] to set + * the seed must be used instead if a custom seed is desired. + * + * @author Daniel Dyer (Java Port) + * @author Makoto Matsumoto and Takuji Nishimura (original C version) + * @author Eben Howard - http://squidpony.com - howard@squidpony.com * @author Lewis Potter - * @author Eben Howard - http://squidpony.com */ public class RNG extends Random { + // The actual seed size isn't that important, but it should be a multiple of 4. + private static final int SEED_SIZE_BYTES = 16; + // Magic numbers from original C version. + private static final int N = 624; + private static final int M = 397; + private static final int[] MAG01 = {0, 0x9908b0df}; + private static final int UPPER_MASK = 0x80000000; + private static final int LOWER_MASK = 0x7fffffff; + private static final int BOOTSTRAP_SEED = 19650218; + private static final int BOOTSTRAP_FACTOR = 1812433253; + private static final int SEED_FACTOR1 = 1664525; + private static final int SEED_FACTOR2 = 1566083941; + private static final int GENERATE_MASK1 = 0x9d2c5680; + private static final int GENERATE_MASK2 = 0xefc60000; + private final byte[] seed; + // Lock to prevent concurrent modification of the RNG's internal state. + private final ReentrantLock lock = new ReentrantLock(); + private final int[] mt = new int[N]; // State vector. + private int mtIndex = 0; // Index into state vector. + private static final int BITWISE_BYTE_TO_INT = 0x000000FF; + + /** + * Creates a new RNG and seeds it using the default seeding strategy. + */ + public RNG() { + this((new SecureRandom()).generateSeed(SEED_SIZE_BYTES)); + } + + /** + * Ignores the seed parameter. For setting the seed, please use the + * constructor that takes a byte[] + * + * @param seed + */ + public RNG(long seed) { + this(); + } + + /** + * Creates an RNG and seeds it with the specified seed data. + * + * @param seed The seed data used to initialize the RNG. + */ + public RNG(byte[] seed) { + if (seed == null || seed.length != SEED_SIZE_BYTES) { + throw new IllegalArgumentException("Mersenne Twister RNG requires a 128-bit (16-byte) seed."); + } + this.seed = seed.clone(); + + int[] seedInts = convertBytesToInts(this.seed); + + // This section is translated from the init_genrand code in the C version. + mt[0] = BOOTSTRAP_SEED; + for (mtIndex = 1; mtIndex < N; mtIndex++) { + mt[mtIndex] = (BOOTSTRAP_FACTOR + * (mt[mtIndex - 1] ^ (mt[mtIndex - 1] >>> 30)) + + mtIndex); + } + + // This section is translated from the init_by_array code in the C version. + int i = 1; + int j = 0; + for (int k = Math.max(N, seedInts.length); k > 0; k--) { + mt[i] = (mt[i] ^ ((mt[i - 1] ^ (mt[i - 1] >>> 30)) * SEED_FACTOR1)) + seedInts[j] + j; + i++; + j++; + if (i >= N) { + mt[0] = mt[N - 1]; + i = 1; + } + if (j >= seedInts.length) { + j = 0; + } + } + for (int k = N - 1; k > 0; k--) { + mt[i] = (mt[i] ^ ((mt[i - 1] ^ (mt[i - 1] >>> 30)) * SEED_FACTOR2)) - i; + i++; + if (i >= N) { + mt[0] = mt[N - 1]; + i = 1; + } + } + mt[0] = UPPER_MASK; // Most significant bit is 1 - guarantees non-zero initial array. + } + + /** + * Take four bytes from the specified position in the specified block and + * convert them into a 32-bit int, using the big-endian convention. + * + * @param bytes The data to read from. + * @param offset The position to start reading the 4-byte int from. + * @return The 32-bit integer represented by the four bytes. + */ + public static int convertBytesToInt(byte[] bytes, int offset) { + return (BITWISE_BYTE_TO_INT & bytes[offset + 3]) + | ((BITWISE_BYTE_TO_INT & bytes[offset + 2]) << 8) + | ((BITWISE_BYTE_TO_INT & bytes[offset + 1]) << 16) + | ((BITWISE_BYTE_TO_INT & bytes[offset]) << 24); + } + + /** + * Convert an array of bytes into an array of ints. 4 bytes from the input + * data map to a single int in the output data. + * + * @param bytes The data to read from. + * @return An array of 32-bit integers constructed from the data. + * @since 1.1 + */ + public static int[] convertBytesToInts(byte[] bytes) { + if (bytes.length % 4 != 0) { + throw new IllegalArgumentException("Number of input bytes must be a multiple of 4."); + } + int[] ints = new int[bytes.length / 4]; + for (int i = 0; i < ints.length; i++) { + ints[i] = convertBytesToInt(bytes, i * 4); + } + return ints; + } + + /** + * {@inheritDoc} + */ + public byte[] getSeed() { + return seed.clone(); + } + + @Override + public void setSeed(long seed) { + //ignored + } + + /** + * {@inheritDoc} + */ + @Override + protected final int next(int bits) { + int y; + try { + lock.lock(); + if (mtIndex >= N) // Generate N ints at a time. + { + int kk; + for (kk = 0; kk < N - M; kk++) { + y = (mt[kk] & UPPER_MASK) | (mt[kk + 1] & LOWER_MASK); + mt[kk] = mt[kk + M] ^ (y >>> 1) ^ MAG01[y & 0x1]; + } + for (; kk < N - 1; kk++) { + y = (mt[kk] & UPPER_MASK) | (mt[kk + 1] & LOWER_MASK); + mt[kk] = mt[kk + (M - N)] ^ (y >>> 1) ^ MAG01[y & 0x1]; + } + y = (mt[N - 1] & UPPER_MASK) | (mt[0] & LOWER_MASK); + mt[N - 1] = mt[M - 1] ^ (y >>> 1) ^ MAG01[y & 0x1]; + + mtIndex = 0; + } + + y = mt[mtIndex++]; + } finally { + lock.unlock(); + } + // Tempering + y ^= (y >>> 11); + y ^= (y << 7) & GENERATE_MASK1; + y ^= (y << 15) & GENERATE_MASK2; + y ^= (y >>> 18); + + return y >>> (32 - bits); + } + /** * Returns a value from a even distribution from min (inclusive) to max * (exclusive). diff --git a/src/main/java/squidpony/squidutility/Pair.java b/src/main/java/squidpony/squidutility/Pair.java index b38046889a..8d80cee511 100644 --- a/src/main/java/squidpony/squidutility/Pair.java +++ b/src/main/java/squidpony/squidutility/Pair.java @@ -3,10 +3,12 @@ import java.util.Objects; /** - * A Collection that stores two values related in some way. In additions to - * having values accessible by key, they may also be accessed by value; + * A Collection that stores two values related in some way. * - * @author Eben Howard - http://squidpony.com - eben@squidpony.com + * In additions to having values accessible by key, they may also be accessed by + * value. + * + * @author Eben Howard - http://squidpony.com - howard@squidpony.com */ public class Pair { diff --git a/src/main/java/squidpony/squidutility/SCollections.java b/src/main/java/squidpony/squidutility/SCollections.java index c49c1e443b..9a39ceb4d8 100644 --- a/src/main/java/squidpony/squidutility/SCollections.java +++ b/src/main/java/squidpony/squidutility/SCollections.java @@ -7,7 +7,7 @@ /** * This utility class contains functions for working with Collections. * - * @author Eben Howard - http://squidpony.com - eben@squidpony.com + * @author Eben Howard - http://squidpony.com - howard@squidpony.com */ public class SCollections {