mirror of
https://github.com/JHUAPL/Glum.git
synced 2026-01-07 00:03:50 -05:00
Initial release
This commit is contained in:
9
.classpath
Normal file
9
.classpath
Normal file
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="lib" path="lib/miglayout-3.7.2-swing.jar" sourcepath="lib/miglayout-3.7.2-sources.jar"/>
|
||||
<classpathentry kind="lib" path="lib/dockingFramesCore.jar" sourcepath="lib/dockingFramesCore-src.jar"/>
|
||||
<classpathentry kind="lib" path="lib/guava-12.0.jar" sourcepath="lib/guava-12.0-sources.jar"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
||||
17
.project
Normal file
17
.project
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>glum</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
18
buildGlumBin.jardesc
Normal file
18
buildGlumBin.jardesc
Normal file
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<jardesc>
|
||||
<jar path="glum/bin/glum.jar"/>
|
||||
<options buildIfNeeded="true" compress="true" descriptionLocation="/glum/buildGlumBin.jardesc" exportErrors="false" exportWarnings="true" includeDirectoryEntries="false" overwrite="true" saveDescription="false" storeRefactorings="false" useSourceFolders="false"/>
|
||||
<storedRefactorings deprecationInfo="true" structuralOnly="false"/>
|
||||
<selectedProjects/>
|
||||
<manifest generateManifest="false" manifestLocation="/glum/src/Manifest.txt" manifestVersion="1.0" reuseManifest="false" saveManifest="false" usesManifest="true">
|
||||
<sealing sealJar="false">
|
||||
<packagesToSeal/>
|
||||
<packagesToUnSeal/>
|
||||
</sealing>
|
||||
</manifest>
|
||||
<selectedElements exportClassFiles="true" exportJavaFiles="false" exportOutputFolder="false">
|
||||
<javaElement handleIdentifier="=glum/src"/>
|
||||
<folder path="/glum/build/doc"/>
|
||||
<folder path="/glum/build/classes"/>
|
||||
</selectedElements>
|
||||
</jardesc>
|
||||
18
buildGlumSrc.jardesc
Normal file
18
buildGlumSrc.jardesc
Normal file
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<jardesc>
|
||||
<jar path="glum/build/glum-src.jar"/>
|
||||
<options buildIfNeeded="true" compress="true" descriptionLocation="/glum/buildGlumSrc.jardesc" exportErrors="false" exportWarnings="true" includeDirectoryEntries="false" overwrite="true" saveDescription="false" storeRefactorings="false" useSourceFolders="false"/>
|
||||
<storedRefactorings deprecationInfo="true" structuralOnly="false"/>
|
||||
<selectedProjects/>
|
||||
<manifest generateManifest="false" manifestLocation="/glum/src/Manifest.txt" manifestVersion="1.0" reuseManifest="false" saveManifest="false" usesManifest="false">
|
||||
<sealing sealJar="false">
|
||||
<packagesToSeal/>
|
||||
<packagesToUnSeal/>
|
||||
</sealing>
|
||||
</manifest>
|
||||
<selectedElements exportClassFiles="false" exportJavaFiles="true" exportOutputFolder="false">
|
||||
<javaElement handleIdentifier="=glum/src"/>
|
||||
<folder path="/glum/build/doc"/>
|
||||
<folder path="/glum/build/classes"/>
|
||||
</selectedElements>
|
||||
</jardesc>
|
||||
BIN
lib/dockingFramesCore-src.jar
Normal file
BIN
lib/dockingFramesCore-src.jar
Normal file
Binary file not shown.
BIN
lib/dockingFramesCore.jar
Normal file
BIN
lib/dockingFramesCore.jar
Normal file
Binary file not shown.
BIN
lib/guava-12.0-sources.jar
Normal file
BIN
lib/guava-12.0-sources.jar
Normal file
Binary file not shown.
BIN
lib/guava-12.0.jar
Normal file
BIN
lib/guava-12.0.jar
Normal file
Binary file not shown.
BIN
lib/miglayout-3.7.2-sources.jar
Normal file
BIN
lib/miglayout-3.7.2-sources.jar
Normal file
Binary file not shown.
BIN
lib/miglayout-3.7.2-swing.jar
Executable file
BIN
lib/miglayout-3.7.2-swing.jar
Executable file
Binary file not shown.
1
src/Manifest.txt
Normal file
1
src/Manifest.txt
Normal file
@@ -0,0 +1 @@
|
||||
Class-Path: lib/guava-12.0.jar lib/miglayout-3.7.2-sources.jar
|
||||
95
src/glum/coord/Convert.java
Normal file
95
src/glum/coord/Convert.java
Normal file
@@ -0,0 +1,95 @@
|
||||
package glum.coord;
|
||||
|
||||
/**
|
||||
* Contains conversion multipliers to/from feet, yards, meters, data miles, and nautical miles, as well as angular
|
||||
* values to/from degrees and radians. To convert a value <code>X</code> in units of <code>U</code> to units of
|
||||
* <code>V</code>, use <code>X * Convert.U_TO_V</code>.
|
||||
*/
|
||||
public class Convert
|
||||
{
|
||||
public static final double FEET_TO_METERS = 0.3048;
|
||||
public static final double DM_TO_METERS = 1828.8;
|
||||
public static final double NM_TO_METERS = 1852.0;
|
||||
public static final double MILES_TO_METERS = 1609.344;
|
||||
public static final double YARDS_TO_METERS = 0.9144; // 3 * FEET_TO_METERS
|
||||
|
||||
public static final double METERS_TO_FEET = 1.0 / FEET_TO_METERS;
|
||||
public static final double DM_TO_FEET = 6000.0;
|
||||
public static final double NM_TO_FEET = NM_TO_METERS * METERS_TO_FEET;
|
||||
public static final double MILES_TO_FEET = 5280.0;
|
||||
public static final double YARDS_TO_FEET = 3.0;
|
||||
|
||||
public static final double METERS_TO_DM = 1.0 / DM_TO_METERS;
|
||||
public static final double FEET_TO_DM = FEET_TO_METERS * METERS_TO_DM;
|
||||
public static final double NM_TO_DM = NM_TO_METERS * METERS_TO_DM;
|
||||
public static final double MILES_TO_DM = MILES_TO_METERS * METERS_TO_DM;
|
||||
public static final double YARDS_TO_DM = YARDS_TO_METERS * METERS_TO_DM;
|
||||
|
||||
public static final double METERS_TO_NM = 1.0 / NM_TO_METERS;
|
||||
public static final double FEET_TO_NM = FEET_TO_METERS * METERS_TO_NM;
|
||||
public static final double DM_TO_NM = DM_TO_METERS * METERS_TO_NM;
|
||||
public static final double MILES_TO_NM = MILES_TO_METERS * METERS_TO_NM;
|
||||
public static final double YARDS_TO_NM = YARDS_TO_METERS * NM_TO_METERS;
|
||||
|
||||
public static final double METERS_TO_MILES = 1.0 / MILES_TO_METERS;
|
||||
public static final double FEET_TO_MILES = FEET_TO_METERS * METERS_TO_MILES;
|
||||
public static final double DM_TO_MILES = DM_TO_METERS * METERS_TO_MILES;
|
||||
public static final double NM_TO_MILES = NM_TO_METERS * METERS_TO_MILES;
|
||||
public static final double YARDS_TO_MILES = YARDS_TO_METERS * METERS_TO_MILES;
|
||||
|
||||
public static final double METERS_TO_YARDS = 1.0 / YARDS_TO_METERS;
|
||||
public static final double FEET_TO_YARDS = 1.0 / 3.0;
|
||||
public static final double DM_TO_YARDS = 2000.0;
|
||||
public static final double NM_TO_YARDS = NM_TO_METERS * METERS_TO_YARDS;
|
||||
public static final double MILES_TO_YARDS = 1760.0;
|
||||
|
||||
public static final double RAD_TO_DEG = 180.0 / Math.PI;
|
||||
public static final double DEG_TO_RAD = Math.PI / 180.0;
|
||||
|
||||
public static final double SECS_TO_MSECS = 1000.0;
|
||||
public static final double MSECS_TO_SECS = 1.0 / SECS_TO_MSECS;
|
||||
|
||||
public static final int MINS_TO_SECS = 60;
|
||||
public static final int HOURS_TO_MINS = 60;
|
||||
public static final int HOURS_TO_SECS = HOURS_TO_MINS * MINS_TO_SECS;
|
||||
|
||||
public static final double SECS_TO_MINS = 1 / MINS_TO_SECS;
|
||||
public static final double MINS_TO_HOURS = 1 / HOURS_TO_MINS;
|
||||
public static final double SECS_TO_HOURS = 1 / HOURS_TO_SECS;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
private Convert()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an angle to a bearing
|
||||
*/
|
||||
public static double angleToBearing(double aAngle)
|
||||
{
|
||||
double bearing;
|
||||
|
||||
bearing = 180 - (aAngle + 90);
|
||||
if (bearing < 0)
|
||||
bearing += 360;
|
||||
|
||||
return bearing;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a bearing to an angle
|
||||
*/
|
||||
public static double bearingToAngle(double aBearing)
|
||||
{
|
||||
double angle;
|
||||
|
||||
angle = 180 - (aBearing + 90);
|
||||
if (angle < 0)
|
||||
angle += 360;
|
||||
|
||||
return angle;
|
||||
}
|
||||
|
||||
}
|
||||
197
src/glum/coord/CoordUtil.java
Normal file
197
src/glum/coord/CoordUtil.java
Normal file
@@ -0,0 +1,197 @@
|
||||
package glum.coord;
|
||||
|
||||
|
||||
/** Provides a few useful functions on coordinates, such as converting
|
||||
* to a user-presentable string.
|
||||
*/
|
||||
public class CoordUtil
|
||||
{
|
||||
/** Convert a Lat/Lon to a pair of DEG:MM:SS H strings. H is the
|
||||
* hemisphere, N or S for lat, E or W for lon. The default separator
|
||||
* string LL_SEP is used.
|
||||
*/
|
||||
public static String LatLonToString (LatLon ll)
|
||||
{
|
||||
return ll == null ? "" : LatLonToString (ll, LL_SEP);
|
||||
}
|
||||
|
||||
/** Same as the other LatLonToString, excepts this one uses the
|
||||
* given <code>sep</code> string to separate the Lat and Lon.
|
||||
*/
|
||||
public static String LatLonToString (LatLon ll, String sep)
|
||||
{
|
||||
return ll == null ? "" :
|
||||
LatToString (ll.lat) + LL_SEP + LonToString (ll.lon);
|
||||
}
|
||||
|
||||
/** Converts the given <code>lat</code> to DD:MM:SS H. */
|
||||
|
||||
public static String LatToString (double lat)
|
||||
{
|
||||
return LatToString (lat, true);
|
||||
}
|
||||
|
||||
/** Converts the given <code>lat</code> to DD:MM:SS H if
|
||||
* <code>include_seconds</code> is true. If it's false, then the
|
||||
* :SS part is left off.
|
||||
*/
|
||||
|
||||
public static String LatToString (double lat, boolean include_seconds)
|
||||
{
|
||||
DMS dms = new DMS (lat);
|
||||
StringBuffer s = new StringBuffer();
|
||||
|
||||
if ( dms.degrees < 10 )
|
||||
s.append ("0");
|
||||
s.append (dms.degrees);
|
||||
s.append (":");
|
||||
if ( dms.minutes < 10 )
|
||||
s.append ("0");
|
||||
s.append (dms.minutes);
|
||||
if ( include_seconds )
|
||||
{
|
||||
s.append (":");
|
||||
if ( dms.seconds < 10 )
|
||||
s.append ("0");
|
||||
s.append (dms.seconds);
|
||||
}
|
||||
s.append (lat >= 0 ? " N" : " S");
|
||||
return s.toString();
|
||||
}
|
||||
|
||||
/** Similar to <code>LatToString</code> except that the degrees
|
||||
* part is DDD instead of DD. */
|
||||
|
||||
public static String LonToString (double lon)
|
||||
{
|
||||
return LonToString (lon, true);
|
||||
}
|
||||
|
||||
/** Similar to <code>LatToString</code> except that the degrees
|
||||
* part is DDD instead of DD. */
|
||||
|
||||
public static String LonToString (double lon, boolean include_seconds)
|
||||
{
|
||||
DMS dms = new DMS (lon);
|
||||
StringBuffer s = new StringBuffer();
|
||||
|
||||
if ( dms.degrees < 100 )
|
||||
s.append ("0");
|
||||
if ( dms.degrees < 10 )
|
||||
s.append ("0");
|
||||
s.append (dms.degrees);
|
||||
s.append (":");
|
||||
if ( dms.minutes < 10 )
|
||||
s.append ("0");
|
||||
s.append (dms.minutes);
|
||||
if ( include_seconds )
|
||||
{
|
||||
s.append (":");
|
||||
if ( dms.seconds < 10 )
|
||||
s.append ("0");
|
||||
s.append (dms.seconds);
|
||||
}
|
||||
s.append (lon >= 0 ? " E" : " W");
|
||||
return s.toString();
|
||||
}
|
||||
|
||||
/** Converts <code>dmsh_string</code> to a double value.
|
||||
* The string format should match the output of the
|
||||
* LatToString formats, including hemisphere.
|
||||
* If a hemisphere character is not part of the string, the
|
||||
* returned value will be non-negative.
|
||||
*/
|
||||
public static double StringToLat (String dmsh_string)
|
||||
{
|
||||
if ( dmsh_string == null || dmsh_string.length() == 0 )
|
||||
return 0.0;
|
||||
|
||||
int dms [] = StringToDMS (dmsh_string);
|
||||
|
||||
if ( dms.length == 3 )
|
||||
return new Degrees (dms[0], dms[1], dms[2]).degrees;
|
||||
else return 0.0;
|
||||
}
|
||||
|
||||
/** {@see StringToLat} */
|
||||
|
||||
public static double StringToLon (String dmsh_string)
|
||||
{
|
||||
// Because we aren't doing any range or hemisphere error
|
||||
// checking, a lon value is identical to a lat value.
|
||||
return StringToLat (dmsh_string);
|
||||
}
|
||||
|
||||
/** Converts <code>dmsh_string</code> to a an array of
|
||||
* 3 ints representing degrees, minutes, and seconds.
|
||||
* if a hemisphere character is present (one of NSEW or
|
||||
* nsew), and it represents a souther or western hemisphere,
|
||||
* then the degrees value, in index 0 of the returned array,
|
||||
* will be a non-positive number.
|
||||
*/
|
||||
public static int [] StringToDMS (String dmsh_string)
|
||||
{
|
||||
if ( dmsh_string == null || dmsh_string.length() == 0 )
|
||||
return null;
|
||||
|
||||
char chars [] = dmsh_string.toCharArray();
|
||||
int dms [] = new int [ 3 ];
|
||||
|
||||
dms[0] = 0;
|
||||
for ( int i = 0, j = 0; i < chars.length; i++ )
|
||||
{
|
||||
char c = chars[i];
|
||||
|
||||
if ( c == ' ' || c == ' ' ) // Space or tab.
|
||||
continue;
|
||||
else if ( c >= '0' && c <= '9' && j < 3 )
|
||||
dms[j] = dms[j] * 10 + c - '0';
|
||||
else if ( c == ':' )
|
||||
{
|
||||
j++;
|
||||
dms[j] = 0;
|
||||
}
|
||||
else if ( c == 'S' || c == 's' || c == 'W' || c == 'w' )
|
||||
dms[0] = -dms[0];
|
||||
}
|
||||
|
||||
return dms;
|
||||
}
|
||||
|
||||
public static class DMS
|
||||
{
|
||||
public DMS (double deg)
|
||||
{
|
||||
if ( deg < 0 ) deg = -deg;
|
||||
degrees = (int) deg;
|
||||
minutes = (int) (deg * 60) % 60;
|
||||
seconds = (int) (deg * 3600) % 60;
|
||||
}
|
||||
public int degrees, minutes, seconds;
|
||||
}
|
||||
|
||||
public static class Degrees
|
||||
{
|
||||
public Degrees (int deg, int min, int sec)
|
||||
{
|
||||
degrees = Math.abs (deg) +
|
||||
Math.abs(min) / 60.0 +
|
||||
Math.abs(sec) / 3600.0;
|
||||
if ( deg < 0 || min < 0 || sec < 0 )
|
||||
degrees = -degrees;
|
||||
}
|
||||
public Degrees (int deg, int min, int sec, char hemisphere)
|
||||
{
|
||||
this (deg, min, sec);
|
||||
if ( hemisphere == 'N' || hemisphere == 'n' ||
|
||||
hemisphere == 'E' || hemisphere == 'e' )
|
||||
degrees = Math.abs (degrees);
|
||||
else if ( hemisphere == 'S' || hemisphere == 's' ||
|
||||
hemisphere == 'W' || hemisphere == 'w' )
|
||||
degrees = -Math.abs (degrees);
|
||||
}
|
||||
public double degrees;
|
||||
}
|
||||
|
||||
public static String LL_SEP = " / ";
|
||||
}
|
||||
43
src/glum/coord/Epsilon.java
Normal file
43
src/glum/coord/Epsilon.java
Normal file
@@ -0,0 +1,43 @@
|
||||
package glum.coord;
|
||||
|
||||
/** Determines if two numbers are close, usually as a way to say
|
||||
* that they are equal. Close is defined to mean that their difference
|
||||
* is less than some small number, which is either supplied by the caller
|
||||
* or is EPSILON.
|
||||
* <p>For longitude near the equator, a difference of EPSILON is about
|
||||
* 3.65 feet (where the earth's circumference is about 21913.3 DM, or
|
||||
* about 60.87 DM per degree longitude). For DataMile measurements, it's
|
||||
* about 0.72 inches.
|
||||
*/
|
||||
|
||||
public class Epsilon
|
||||
{
|
||||
/** The measure of closeness; set to 0.00001. */
|
||||
public static final double EPSILON = 0.00001;
|
||||
|
||||
public static boolean close (float a, float b)
|
||||
{
|
||||
float diff = a - b;
|
||||
return diff < EPSILON && diff > -EPSILON;
|
||||
}
|
||||
|
||||
public static boolean close (float a, float b, float epsilon)
|
||||
{
|
||||
float diff = a - b;
|
||||
return diff < epsilon && diff > -epsilon;
|
||||
}
|
||||
|
||||
public static boolean close (double a, double b)
|
||||
{
|
||||
double diff = a - b;
|
||||
return diff < EPSILON && diff > -EPSILON;
|
||||
}
|
||||
|
||||
public static boolean close (double a, double b, float epsilon)
|
||||
{
|
||||
double diff = a - b;
|
||||
return diff < EPSILON && diff > -EPSILON;
|
||||
}
|
||||
|
||||
private Epsilon () { }
|
||||
}
|
||||
97
src/glum/coord/GeoUtil.java
Normal file
97
src/glum/coord/GeoUtil.java
Normal file
@@ -0,0 +1,97 @@
|
||||
package glum.coord;
|
||||
|
||||
/**
|
||||
* Contains a collection of utility methods to perform linear algebra using the objects from this package.
|
||||
*/
|
||||
public class GeoUtil
|
||||
{
|
||||
/**
|
||||
* realSqr returns aNum*aNum
|
||||
*/
|
||||
public static double realSqr(double aNum)
|
||||
{
|
||||
return aNum * aNum;
|
||||
}
|
||||
|
||||
/**
|
||||
* computeDotProduct - Returns the dot product of vector1 and vector2
|
||||
*/
|
||||
public static double computeDotProduct(Point3D vector1, Point3D vector2)
|
||||
{
|
||||
return vector1.x * vector2.x + vector1.y * vector2.y + vector1.z * vector2.z;
|
||||
}
|
||||
|
||||
/**
|
||||
* computeDistance - Returns the distance between pt1 and pt2
|
||||
*/
|
||||
public static double computeDistance(Point3D pt1, Point3D pt2)
|
||||
{
|
||||
return Math.sqrt(realSqr(pt1.x - pt2.x) + realSqr(pt1.y - pt2.y) + realSqr(pt1.z - pt2.z));
|
||||
}
|
||||
|
||||
/**
|
||||
* computeDistanceSquare - Returns the squared distance between pt1 and pt2
|
||||
*/
|
||||
public static double computeDistanceSquare(Point3D pt1, Point3D pt2)
|
||||
{
|
||||
return realSqr(pt1.x - pt2.x) + realSqr(pt1.y - pt2.y) + realSqr(pt1.z - pt2.z);
|
||||
}
|
||||
|
||||
/**
|
||||
* computeLength - Returns the magnitude of aVector
|
||||
*/
|
||||
public static double computeLength(Point3D aVector)
|
||||
{
|
||||
return Math.sqrt(realSqr(aVector.x) + realSqr(aVector.y) + realSqr(aVector.z));
|
||||
}
|
||||
|
||||
/**
|
||||
* computeNormal - Returns the R.H.R normal defined by the 3 points
|
||||
*/
|
||||
public static void computeNormal(Point3D pt1, Point3D pt2, Point3D pt3, Point3D aNormal)
|
||||
{
|
||||
Point3D vector1, vector2;
|
||||
|
||||
vector1 = new Point3D();
|
||||
vector2 = new Point3D();
|
||||
computeVector(pt1, pt3, vector1);
|
||||
computeVector(pt3, pt2, vector2);
|
||||
|
||||
// ! Not sure why I have to negate all the values; Need to refer to linear alg.
|
||||
//! aNormal.x = vector1.y*vector2.z - vector1.z*vector2.y;
|
||||
//! aNormal.y = vector1.z*vector2.x - vector1.x*vector2.z;
|
||||
//! aNormal.z = vector1.x*vector2.y - vector1.y*vector2.x;
|
||||
aNormal.x = -(vector1.y * vector2.z - vector1.z * vector2.y);
|
||||
aNormal.y = -(vector1.z * vector2.x - vector1.x * vector2.z);
|
||||
aNormal.z = -(vector1.x * vector2.y - vector1.y * vector2.x);
|
||||
|
||||
// Normalize the vector
|
||||
normalizeVector(aNormal);
|
||||
}
|
||||
|
||||
/**
|
||||
* computeVector - Returns the vector defined by the 2 points
|
||||
*/
|
||||
public static void computeVector(Point3D pt1, Point3D pt2, Point3D aVector)
|
||||
{
|
||||
aVector.x = pt2.x - pt1.x;
|
||||
aVector.y = pt2.y - pt1.y;
|
||||
aVector.z = pt2.z - pt1.z;
|
||||
}
|
||||
|
||||
/**
|
||||
* normalizeVector - Normalizes aVector so that its length is 1
|
||||
*/
|
||||
public static void normalizeVector(Point3D aVector)
|
||||
{
|
||||
double length;
|
||||
|
||||
length = computeLength(aVector);
|
||||
|
||||
// Normalize the vector
|
||||
aVector.x = aVector.x / length;
|
||||
aVector.y = aVector.y / length;
|
||||
aVector.z = aVector.z / length;
|
||||
}
|
||||
|
||||
}
|
||||
111
src/glum/coord/LatLon.java
Normal file
111
src/glum/coord/LatLon.java
Normal file
@@ -0,0 +1,111 @@
|
||||
package glum.coord;
|
||||
|
||||
/** Simple class for Lat/Lon values. */
|
||||
public class LatLon
|
||||
{
|
||||
public double lat;
|
||||
public double lon;
|
||||
|
||||
public LatLon()
|
||||
{
|
||||
}
|
||||
|
||||
public LatLon(LatLon latlon)
|
||||
{
|
||||
if (latlon != null)
|
||||
{
|
||||
lat = latlon.lat;
|
||||
lon = latlon.lon;
|
||||
}
|
||||
}
|
||||
|
||||
public LatLon(double lat, double lon)
|
||||
{
|
||||
this.lat = lat;
|
||||
this.lon = lon;
|
||||
}
|
||||
|
||||
public LatLon(String lat_string, String lon_string)
|
||||
{
|
||||
set(lat_string, lon_string);
|
||||
}
|
||||
|
||||
public void set(double lat, double lon)
|
||||
{
|
||||
this.lat = lat;
|
||||
this.lon = lon;
|
||||
}
|
||||
|
||||
public void set(LatLon latlon)
|
||||
{
|
||||
if (latlon != null)
|
||||
{
|
||||
lat = latlon.lat;
|
||||
lon = latlon.lon;
|
||||
}
|
||||
}
|
||||
|
||||
public void set(String lat_string, String lon_string)
|
||||
{
|
||||
lat = CoordUtil.StringToLat(lat_string);
|
||||
lon = CoordUtil.StringToLon(lon_string);
|
||||
}
|
||||
|
||||
public void normalize()
|
||||
{
|
||||
if (lat > 90)
|
||||
lat = 90;
|
||||
else if (lat < -90)
|
||||
lat = -90;
|
||||
|
||||
if (lon > 180)
|
||||
lon -= 360;
|
||||
else if (lon < -180)
|
||||
lon += 360;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests to see if the given object is the same lat/lon as this position.
|
||||
* "Same" really means "very, very close," as defined by {@link Epsilon}.
|
||||
*
|
||||
* @return True if obj is a LatLon and is very close to our lat/lon position.
|
||||
* False otherwise.
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
return (obj instanceof LatLon) && Epsilon.close(lat, ((LatLon)obj).lat) && Epsilon.close(lon, ((LatLon)obj).lon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return CoordUtil.LatLonToString(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the change in latitude
|
||||
*/
|
||||
static public double computeDeltaLat(double lat1, double lat2)
|
||||
{
|
||||
return lat2 - lat1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the change in longitude
|
||||
*/
|
||||
static public double computeDeltaLon(double lon1, double lon2)
|
||||
{
|
||||
double dLon;
|
||||
|
||||
dLon = lon2 - lon1;
|
||||
if (Math.abs(dLon) < 180)
|
||||
return dLon;
|
||||
|
||||
if (dLon > 180)
|
||||
return dLon - 360;
|
||||
else
|
||||
return dLon + 360;
|
||||
}
|
||||
|
||||
}
|
||||
37
src/glum/coord/Point2D.java
Normal file
37
src/glum/coord/Point2D.java
Normal file
@@ -0,0 +1,37 @@
|
||||
package glum.coord;
|
||||
|
||||
public class Point2D
|
||||
{
|
||||
public double x;
|
||||
public double y;
|
||||
|
||||
public Point2D () { }
|
||||
|
||||
public Point2D (Point2D pt)
|
||||
{ if ( pt != null ) { x = pt.x; y = pt.y; } }
|
||||
|
||||
public Point2D (double x, double y)
|
||||
{ this.x = x; this.y = y; }
|
||||
|
||||
public void set (double x, double y)
|
||||
{ this.x = x; this.y = y; }
|
||||
|
||||
public void set (Point2D pt)
|
||||
{ if ( pt != null ) { x = pt.x; y = pt.y; } }
|
||||
|
||||
public double distance (Point2D aPt)
|
||||
{
|
||||
if (aPt == null)
|
||||
return 0;
|
||||
|
||||
return Math.sqrt((aPt.x - x)*(aPt.x - x) + (aPt.y - y)*(aPt.y - y));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals (Object obj)
|
||||
{
|
||||
return (obj instanceof Point2D) &&
|
||||
Epsilon.close (x, ((Point2D) obj).x) &&
|
||||
Epsilon.close (y, ((Point2D) obj).y);
|
||||
}
|
||||
}
|
||||
27
src/glum/coord/Point2Di.java
Normal file
27
src/glum/coord/Point2Di.java
Normal file
@@ -0,0 +1,27 @@
|
||||
package glum.coord;
|
||||
|
||||
public class Point2Di
|
||||
{
|
||||
public int x;
|
||||
public int y;
|
||||
|
||||
public Point2Di () { }
|
||||
|
||||
public Point2Di (Point2Di pt)
|
||||
{ if ( pt != null ) { x = pt.x; y = pt.y; } }
|
||||
|
||||
public Point2Di (int x, int y) { this.x = x; this.y = y; }
|
||||
|
||||
public void set (int x, int y) { this.x = x; this.y = y; }
|
||||
|
||||
public void set (Point2Di pt)
|
||||
{ if ( pt != null ) { x = pt.x; y = pt.y; } }
|
||||
|
||||
@Override
|
||||
public boolean equals (Object obj)
|
||||
{
|
||||
return (obj instanceof Point2Di) &&
|
||||
x == ((Point2Di) obj).x &&
|
||||
y == ((Point2Di) obj).y;
|
||||
}
|
||||
}
|
||||
42
src/glum/coord/Point3D.java
Normal file
42
src/glum/coord/Point3D.java
Normal file
@@ -0,0 +1,42 @@
|
||||
package glum.coord;
|
||||
|
||||
/** A class for representing any 3-Dimensional vector, which could be
|
||||
* a position, a velocity, or a rotation. No information about units
|
||||
* is assumed or implied.
|
||||
*/
|
||||
|
||||
public class Point3D
|
||||
{
|
||||
public double x;
|
||||
public double y;
|
||||
public double z;
|
||||
|
||||
public Point3D () { }
|
||||
|
||||
public Point3D (Point3D pt)
|
||||
{ if ( pt != null ) { x = pt.x; y = pt.y; z = pt.z; } }
|
||||
|
||||
public Point3D (double x, double y, double z)
|
||||
{ this.x = x; this.y = y; this.z = z; }
|
||||
|
||||
public void set (double x, double y, double z)
|
||||
{ this.x = x; this.y = y; this.z = z; }
|
||||
|
||||
public void set (Point3D pt)
|
||||
{ if ( pt != null ) { x = pt.x; y = pt.y; z = pt.z; } }
|
||||
|
||||
@Override
|
||||
public boolean equals (Object obj)
|
||||
{
|
||||
return (obj instanceof Point3D) &&
|
||||
Epsilon.close (x, ((Point3D) obj).x) &&
|
||||
Epsilon.close (y, ((Point3D) obj).y) &&
|
||||
Epsilon.close (z, ((Point3D) obj).z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return new String("(" + x + ", " + y + ", " + z + ")");
|
||||
}
|
||||
}
|
||||
47
src/glum/coord/RngBrg.java
Normal file
47
src/glum/coord/RngBrg.java
Normal file
@@ -0,0 +1,47 @@
|
||||
package glum.coord;
|
||||
|
||||
public class RngBrg
|
||||
{
|
||||
public double rng;
|
||||
public double brg;
|
||||
|
||||
public RngBrg() { }
|
||||
|
||||
public RngBrg(RngBrg pt)
|
||||
{
|
||||
if ( pt != null )
|
||||
{
|
||||
rng = pt.rng;
|
||||
brg = pt.brg;
|
||||
}
|
||||
}
|
||||
|
||||
public RngBrg (double rng, double brg)
|
||||
{
|
||||
this.rng = rng;
|
||||
this.brg = brg;
|
||||
}
|
||||
|
||||
public void set (double rng, double brg)
|
||||
{
|
||||
this.rng = rng;
|
||||
this.brg = brg;
|
||||
}
|
||||
|
||||
public void set (RngBrg pt)
|
||||
{
|
||||
if ( pt != null )
|
||||
{
|
||||
rng = pt.rng;
|
||||
brg = pt.brg;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals (Object obj)
|
||||
{
|
||||
return (obj instanceof RngBrg) &&
|
||||
Epsilon.close (rng, ((RngBrg) obj).rng) &&
|
||||
Epsilon.close (brg, ((RngBrg) obj).brg);
|
||||
}
|
||||
}
|
||||
26
src/glum/coord/UV.java
Normal file
26
src/glum/coord/UV.java
Normal file
@@ -0,0 +1,26 @@
|
||||
package glum.coord;
|
||||
|
||||
public class UV extends Point2D
|
||||
{
|
||||
public UV ()
|
||||
{
|
||||
x = 0;
|
||||
y = 0;
|
||||
}
|
||||
|
||||
public UV (Point2D pt)
|
||||
{
|
||||
if (pt != null)
|
||||
{
|
||||
x = pt.x;
|
||||
y = pt.y;
|
||||
}
|
||||
}
|
||||
|
||||
public UV (double x, double y)
|
||||
{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
}
|
||||
15
src/glum/database/QueryItem.java
Normal file
15
src/glum/database/QueryItem.java
Normal file
@@ -0,0 +1,15 @@
|
||||
package glum.database;
|
||||
|
||||
public abstract interface QueryItem<G1 extends Enum<?>>
|
||||
{
|
||||
/**
|
||||
* Returns the corresponding value associated with aEnum
|
||||
*/
|
||||
public Object getValue(G1 aEnum);
|
||||
|
||||
/**
|
||||
* Sets in the aObj as the corresponding value to aEnum
|
||||
*/
|
||||
public void setValue(G1 aEnum, Object aObj);
|
||||
|
||||
}
|
||||
62
src/glum/database/QueryItemComparator.java
Normal file
62
src/glum/database/QueryItemComparator.java
Normal file
@@ -0,0 +1,62 @@
|
||||
package glum.database;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
public class QueryItemComparator<G1 extends QueryItem<G2>, G2 extends Enum<?>> implements Comparator<G1>
|
||||
{
|
||||
private G2 sortKey;
|
||||
|
||||
public QueryItemComparator(G2 aSortKey)
|
||||
{
|
||||
sortKey = aSortKey;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public int compare(G1 item1, G1 item2)
|
||||
{
|
||||
Comparable<Object> value1, value2;
|
||||
|
||||
value1 = (Comparable<Object>)item1.getValue(sortKey);
|
||||
value2 = (Comparable<Object>)item2.getValue(sortKey);
|
||||
|
||||
if (value1 == null && value2 == null)
|
||||
return 0;
|
||||
|
||||
if (value1 == null)
|
||||
return -1;
|
||||
|
||||
if (value2 == null)
|
||||
return 1;
|
||||
|
||||
return value1.compareTo(value2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to create a QueryItemComparator by specifying the class and sort Enum.
|
||||
* <P>
|
||||
* This logic is here due to Java's horrible implementation off generics.
|
||||
*/
|
||||
public static <G3 extends QueryItem<G4>, G4 extends Enum<?>> Comparator<G3> spawn(Class<G3> aClass, G4 aEnum)
|
||||
{
|
||||
QueryItemComparator<G3, G4> retComparator;
|
||||
|
||||
retComparator = new QueryItemComparator<G3, G4>(aEnum);
|
||||
return retComparator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to create a QueryItemComparator by specifying just the Enum. Note this method can not be used in a
|
||||
* argument to another method; instead use: {@link #spawn(Class, Enum)}
|
||||
* <P>
|
||||
* This logic is here due to Java's horrible implementation off generics.
|
||||
*/
|
||||
public static <G3 extends QueryItem<G4>, G4 extends Enum<?>> Comparator<G3> spawn(G4 aEnum)
|
||||
{
|
||||
QueryItemComparator<G3, G4> retComparator;
|
||||
|
||||
retComparator = new QueryItemComparator<G3, G4>(aEnum);
|
||||
return retComparator;
|
||||
}
|
||||
|
||||
}
|
||||
120
src/glum/filter/EnumFilter.java
Normal file
120
src/glum/filter/EnumFilter.java
Normal file
@@ -0,0 +1,120 @@
|
||||
package glum.filter;
|
||||
|
||||
import glum.zio.ZinStream;
|
||||
import glum.zio.ZoutStream;
|
||||
import glum.zio.raw.ZioRaw;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
public abstract class EnumFilter<G1, G2 extends Enum<?>> implements ZioRaw, Filter<G1>
|
||||
{
|
||||
// Static config vars
|
||||
private Map<Integer, Enum<?>> fullMap;
|
||||
|
||||
// State vars
|
||||
private Set<Enum<?>> validSet;
|
||||
private boolean isEnabled;
|
||||
|
||||
public EnumFilter(Class<? extends Enum<?>> enumClass)
|
||||
{
|
||||
fullMap = Maps.newLinkedHashMap();
|
||||
for (Enum<?> aEnum : enumClass.getEnumConstants())
|
||||
fullMap.put(aEnum.ordinal(), aEnum);
|
||||
|
||||
validSet = Sets.newLinkedHashSet();
|
||||
isEnabled = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the filter is active.
|
||||
*/
|
||||
public boolean getIsEnabled()
|
||||
{
|
||||
return isEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of valid enums for this filter.
|
||||
*/
|
||||
public List<Enum<?>> getSelectedItems()
|
||||
{
|
||||
return Lists.newArrayList(validSet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets this filter to match aFilter
|
||||
*/
|
||||
public void set(EnumFilter<G1, G2> aFilter)
|
||||
{
|
||||
validSet = Sets.newLinkedHashSet(aFilter.validSet);
|
||||
isEnabled = aFilter.getIsEnabled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether the filter is active.
|
||||
*/
|
||||
public void setIsEnabled(boolean aBool)
|
||||
{
|
||||
isEnabled = aBool;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the list of valid enums for this filter.
|
||||
*/
|
||||
public void setSetSelectedItems(List<Enum<?>> selectedItems)
|
||||
{
|
||||
validSet.clear();
|
||||
validSet.addAll(selectedItems);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void zioReadRaw(ZinStream aStream) throws IOException
|
||||
{
|
||||
int numItems;
|
||||
|
||||
aStream.readVersion(0);
|
||||
|
||||
// Read the payload
|
||||
isEnabled = aStream.readBool();
|
||||
|
||||
validSet.clear();
|
||||
numItems = aStream.readInt();
|
||||
for (int c1 = 0; c1 < numItems; c1++)
|
||||
validSet.add(fullMap.get(aStream.readInt()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void zioWriteRaw(ZoutStream aStream) throws IOException
|
||||
{
|
||||
int numItems;
|
||||
|
||||
aStream.writeVersion(0);
|
||||
|
||||
aStream.writeBool(isEnabled);
|
||||
|
||||
numItems = validSet.size();
|
||||
aStream.writeInt(numItems);
|
||||
for (Enum<?> aEnum : validSet)
|
||||
aStream.writeInt(aEnum.ordinal());
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method that returns whether aValue is within the constraints
|
||||
* specified by this filter.
|
||||
*/
|
||||
protected boolean testIsValid(G2 aEnum)
|
||||
{
|
||||
if (isEnabled == false)
|
||||
return true;
|
||||
|
||||
return validSet.contains(aEnum);
|
||||
}
|
||||
|
||||
}
|
||||
12
src/glum/filter/Filter.java
Normal file
12
src/glum/filter/Filter.java
Normal file
@@ -0,0 +1,12 @@
|
||||
package glum.filter;
|
||||
|
||||
import glum.zio.raw.ZioRaw;
|
||||
|
||||
public interface Filter<G1> extends ZioRaw
|
||||
{
|
||||
/**
|
||||
* Method that returns true if aItem passes this filter
|
||||
*/
|
||||
public boolean isValid(G1 aItem);
|
||||
|
||||
}
|
||||
100
src/glum/filter/FilterUtil.java
Normal file
100
src/glum/filter/FilterUtil.java
Normal file
@@ -0,0 +1,100 @@
|
||||
package glum.filter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.JCheckBox;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import glum.gui.component.GList;
|
||||
import glum.gui.component.GNumberField;
|
||||
|
||||
public class FilterUtil
|
||||
{
|
||||
/**
|
||||
* Utility method to return a sublist of itemList based on aFilter.
|
||||
*/
|
||||
public static <G1> List<G1> applyFilter(List<G1> itemList, Filter<G1> aFilter)
|
||||
{
|
||||
List<G1> retList;
|
||||
|
||||
retList = Lists.newArrayList();
|
||||
for (G1 aItem : itemList)
|
||||
{
|
||||
if (aFilter.isValid(aItem) == true)
|
||||
retList.add(aItem);
|
||||
}
|
||||
|
||||
return retList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to synchronize the specified filter with the associated GUI controls.
|
||||
*/
|
||||
public static void getEnumFilter(EnumFilter<?, Enum<?>> aFilter, JCheckBox mainCB, GList<Enum<?>> mainList)
|
||||
{
|
||||
aFilter.setIsEnabled(mainCB.isSelected());
|
||||
aFilter.setSetSelectedItems(mainList.getSelectedItems());
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to synchronize the associated GUI controls with the specified filter.
|
||||
*/
|
||||
public static void setEnumFilter(EnumFilter<?, Enum<?>> aFilter, JCheckBox mainCB, GList<Enum<?>> mainList)
|
||||
{
|
||||
mainCB.setSelected(aFilter.getIsEnabled());
|
||||
mainList.setSelectedItems(aFilter.getSelectedItems());
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to synchronize the specified filter with the associated GUI controls.
|
||||
*/
|
||||
public static void getRangeFilter(RangeFilter<?> aFilter, JCheckBox mainCB, JCheckBox minCB, JCheckBox maxCB, GNumberField minNF, GNumberField maxNF)
|
||||
{
|
||||
aFilter.setIsEnabled(mainCB.isSelected());
|
||||
aFilter.setUseMin(minCB.isSelected());
|
||||
aFilter.setUseMax(maxCB.isSelected());
|
||||
aFilter.setMinValue(minNF.getValue());
|
||||
aFilter.setMaxValue(maxNF.getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to synchronize the associated GUI controls with the specified filter.
|
||||
*/
|
||||
public static void setRangeGui(RangeFilter<?> aFilter, JCheckBox mainCB, JCheckBox minCB, JCheckBox maxCB, GNumberField minNF, GNumberField maxNF)
|
||||
{
|
||||
mainCB.setSelected(aFilter.getIsEnabled());
|
||||
minCB.setSelected(aFilter.getUseMin());
|
||||
maxCB.setSelected(aFilter.getUseMax());
|
||||
minNF.setValue(aFilter.getMinValue());
|
||||
maxNF.setValue(aFilter.getMaxValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to keep the various GUI components associated with an EnumFilter synchronized.
|
||||
* The mainList will be enabled/disabled based on the selection state of mainCB.
|
||||
*/
|
||||
public static void syncEnumGui(JCheckBox mainCB, GList<Enum<?>> mainList)
|
||||
{
|
||||
boolean isEnabled;
|
||||
|
||||
isEnabled = mainCB.isSelected();
|
||||
mainList.setEnabled(isEnabled);
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to keep the various GUI components associated with an RangeFilter synchronized.
|
||||
* Gui components will be enabled/disabled based on the various check boxes.
|
||||
*/
|
||||
public static void syncRangeGui(JCheckBox mainCB, JCheckBox minCB, JCheckBox maxCB, GNumberField minNF, GNumberField maxNF)
|
||||
{
|
||||
boolean isEnabled;
|
||||
|
||||
isEnabled = mainCB.isSelected();
|
||||
minCB.setEnabled(isEnabled);
|
||||
maxCB.setEnabled(isEnabled);
|
||||
minNF.setEnabled(isEnabled & minCB.isSelected());
|
||||
maxNF.setEnabled(isEnabled & maxCB.isSelected());
|
||||
}
|
||||
|
||||
}
|
||||
32
src/glum/filter/NullFilter.java
Normal file
32
src/glum/filter/NullFilter.java
Normal file
@@ -0,0 +1,32 @@
|
||||
package glum.filter;
|
||||
|
||||
import glum.zio.ZinStream;
|
||||
import glum.zio.ZoutStream;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* A Filter which does not filter anything. Thus the method isValid() always returns true.
|
||||
*/
|
||||
public class NullFilter<G1> implements Filter<G1>
|
||||
{
|
||||
|
||||
@Override
|
||||
public boolean isValid(G1 aItem)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void zioReadRaw(ZinStream aStream) throws IOException
|
||||
{
|
||||
; // Nothing to do
|
||||
}
|
||||
|
||||
@Override
|
||||
public void zioWriteRaw(ZoutStream aStream) throws IOException
|
||||
{
|
||||
; // Nothing to do
|
||||
}
|
||||
|
||||
}
|
||||
122
src/glum/filter/RangeFilter.java
Normal file
122
src/glum/filter/RangeFilter.java
Normal file
@@ -0,0 +1,122 @@
|
||||
package glum.filter;
|
||||
|
||||
import glum.zio.ZinStream;
|
||||
import glum.zio.ZoutStream;
|
||||
import glum.zio.raw.ZioRaw;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Abstract filter which is used to filter a single value between the specified min/max ranges. The only code to write
|
||||
* is the isValid() method and to call the appropriate Constructor. In the isValid() method, you should delegate filter
|
||||
* logic to the method testIsValid() with the quantity of interest, and return the result from the method call.
|
||||
*/
|
||||
public abstract class RangeFilter<G1> implements ZioRaw, Filter<G1>
|
||||
{
|
||||
private boolean isEnabled;
|
||||
private boolean useMin, useMax;
|
||||
private double minValue, maxValue;
|
||||
|
||||
/**
|
||||
* @param aBinCode
|
||||
* Unique identifier used during serialization. The value specified here should not collide with any other
|
||||
* codes for which there is serialization.
|
||||
*/
|
||||
public RangeFilter()
|
||||
{
|
||||
isEnabled = false;
|
||||
useMin = false;
|
||||
useMax = false;
|
||||
minValue = 0;
|
||||
maxValue = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accessor methods
|
||||
*/
|
||||
// @formatter:off
|
||||
public boolean getIsEnabled() { return isEnabled; }
|
||||
public boolean getUseMin() { return useMin; }
|
||||
public boolean getUseMax() { return useMax; }
|
||||
public double getMinValue() { return minValue; }
|
||||
public double getMaxValue() { return maxValue; }
|
||||
|
||||
public void setIsEnabled(boolean aBool) { isEnabled = aBool; }
|
||||
public void setUseMin(boolean aBool) { useMin = aBool; }
|
||||
public void setUseMax(boolean aBool) { useMax = aBool; }
|
||||
public void setMinValue(double aValue) { minValue = aValue; }
|
||||
public void setMaxValue(double aValue) { maxValue = aValue; }
|
||||
// @formatter:on
|
||||
|
||||
/**
|
||||
* Sets this filter to match aFilter
|
||||
*/
|
||||
public void set(RangeFilter<G1> aFilter)
|
||||
{
|
||||
isEnabled = aFilter.getIsEnabled();
|
||||
useMin = aFilter.getUseMin();
|
||||
useMax = aFilter.getUseMax();
|
||||
minValue = aFilter.getMinValue();
|
||||
maxValue = aFilter.getMaxValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void zioReadRaw(ZinStream aStream) throws IOException
|
||||
{
|
||||
byte bSwitch;
|
||||
|
||||
aStream.readVersion(0);
|
||||
|
||||
bSwitch = aStream.readByte();
|
||||
isEnabled = (bSwitch & 0x1) != 0;
|
||||
useMin = (bSwitch & 0x2) != 0;
|
||||
useMax = (bSwitch & 0x4) != 0;
|
||||
|
||||
// isEnabled = aStream.readBoolean();
|
||||
// useMin = aStream.readBoolean();
|
||||
// useMax = aStream.readBoolean();
|
||||
minValue = aStream.readDouble();
|
||||
maxValue = aStream.readDouble();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void zioWriteRaw(ZoutStream aStream) throws IOException
|
||||
{
|
||||
byte bSwitch;
|
||||
|
||||
aStream.writeVersion(0);
|
||||
|
||||
bSwitch = 0;
|
||||
if (isEnabled == true)
|
||||
bSwitch |= 0x1;
|
||||
if (useMin == true)
|
||||
bSwitch |= 0x2;
|
||||
if (useMax == true)
|
||||
bSwitch |= 0x4;
|
||||
aStream.writeByte(bSwitch);
|
||||
|
||||
// aStream.writeBoolean(isEnabled);
|
||||
// aStream.writeBoolean(useMin);
|
||||
// aStream.writeBoolean(useMax);
|
||||
aStream.writeDouble(minValue);
|
||||
aStream.writeDouble(maxValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method that returns whether aValue is within the constraints specified by this filter.
|
||||
*/
|
||||
protected boolean testIsValid(double aValue)
|
||||
{
|
||||
if (isEnabled == false)
|
||||
return true;
|
||||
|
||||
if (useMin == true && aValue < minValue)
|
||||
return false;
|
||||
|
||||
if (useMax == true && aValue > maxValue)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
66
src/glum/gui/FocusUtil.java
Normal file
66
src/glum/gui/FocusUtil.java
Normal file
@@ -0,0 +1,66 @@
|
||||
package glum.gui;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
public class FocusUtil
|
||||
{
|
||||
/**
|
||||
* Adds a keyboard shortcut to bind aKeyStroke for the specified action.
|
||||
* This keyboard shortcut will be executed whenever a child component of aComp has the focus.
|
||||
*/
|
||||
public static void addAncestorKeyBinding(JComponent aComp, String aKeyStroke, Action aAction)
|
||||
{
|
||||
addAncestorKeyBinding(aComp, convertStringToKeyStroke(aKeyStroke), aAction);
|
||||
}
|
||||
|
||||
public static void addAncestorKeyBinding(JComponent aComp, KeyStroke aKeyStroke, Action aAction)
|
||||
{
|
||||
aComp.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(aKeyStroke, aAction);
|
||||
aComp.getActionMap().put(aAction, aAction);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a keyboard shortcut to bind aKeyStroke for the specified action.
|
||||
* This keyboard shortcut will be executed aComp has the focus.
|
||||
*/
|
||||
public static void addFocusKeyBinding(JComponent aComp, String aKeyStroke, Action aAction)
|
||||
{
|
||||
addFocusKeyBinding(aComp, convertStringToKeyStroke(aKeyStroke), aAction);
|
||||
}
|
||||
|
||||
public static void addFocusKeyBinding(JComponent aComp, KeyStroke aKeyStroke, Action aAction)
|
||||
{
|
||||
aComp.getInputMap(JComponent.WHEN_FOCUSED).put(aKeyStroke, aAction);
|
||||
aComp.getActionMap().put(aAction, aAction);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a keyboard shortcut to bind aKeyStroke for the specified action.
|
||||
* This keyboard shortcut will be executed whenever the parent Window has the focus.
|
||||
*/
|
||||
public static void addWindowKeyBinding(JComponent aComp, String aKeyStroke, Action aAction)
|
||||
{
|
||||
addWindowKeyBinding(aComp, convertStringToKeyStroke(aKeyStroke), aAction);
|
||||
}
|
||||
|
||||
public static void addWindowKeyBinding(JComponent aComp, KeyStroke aKeyStroke, Action aAction)
|
||||
{
|
||||
aComp.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(aKeyStroke, aAction);
|
||||
aComp.getActionMap().put(aAction, aAction);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a String to a valid KeyStroke.
|
||||
*/
|
||||
public static KeyStroke convertStringToKeyStroke(String aStr)
|
||||
{
|
||||
KeyStroke aKeyStroke;
|
||||
|
||||
aKeyStroke = KeyStroke.getKeyStroke(aStr);
|
||||
if (aKeyStroke == null)
|
||||
throw new RuntimeException("Failed to convert: [" + aStr + "] to a keystroke.");
|
||||
|
||||
return aKeyStroke;
|
||||
}
|
||||
|
||||
}
|
||||
688
src/glum/gui/GuiUtil.java
Normal file
688
src/glum/gui/GuiUtil.java
Normal file
@@ -0,0 +1,688 @@
|
||||
package glum.gui;
|
||||
|
||||
import glum.gui.icon.IconUtil;
|
||||
import glum.reflect.Function;
|
||||
import glum.reflect.FunctionRunnable;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.Collection;
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.BevelBorder;
|
||||
import javax.swing.event.ChangeListener;
|
||||
|
||||
public class GuiUtil
|
||||
{
|
||||
/**
|
||||
* Method to examine the labels and returns the size of the largest button.
|
||||
*/
|
||||
public static Dimension computePreferredJButtonSize(String... labels)
|
||||
{
|
||||
Dimension tmpDim, maxDim;
|
||||
JButton tmpB;
|
||||
|
||||
maxDim = null;
|
||||
tmpB = new JButton("");
|
||||
|
||||
// Find the label that requires the largest dimension
|
||||
for (String aStr : labels)
|
||||
{
|
||||
if (aStr == null)
|
||||
aStr = "";
|
||||
|
||||
tmpB.setText(aStr);
|
||||
tmpDim = tmpB.getPreferredSize();
|
||||
|
||||
if (maxDim == null || maxDim.getWidth() < tmpDim.getWidth())
|
||||
maxDim = tmpDim;
|
||||
}
|
||||
|
||||
return maxDim;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a JButton with the specified settings
|
||||
*/
|
||||
public static JButton createJButton(String aTitle, ActionListener aActionListener)
|
||||
{
|
||||
JButton tmpB;
|
||||
|
||||
tmpB = new JButton(aTitle);
|
||||
tmpB.addActionListener(aActionListener);
|
||||
return tmpB;
|
||||
}
|
||||
|
||||
public static JButton createJButton(String aTitle, ActionListener aActionListener, Font aFont)
|
||||
{
|
||||
JButton tmpB;
|
||||
|
||||
tmpB = new JButton(aTitle);
|
||||
tmpB.addActionListener(aActionListener);
|
||||
if (aFont != null)
|
||||
tmpB.setFont(aFont);
|
||||
|
||||
return tmpB;
|
||||
}
|
||||
|
||||
public static JButton createJButton(String aTitle, ActionListener aActionListener, Dimension aDimension)
|
||||
{
|
||||
JButton tmpB;
|
||||
|
||||
tmpB = new JButton(aTitle);
|
||||
tmpB.addActionListener(aActionListener);
|
||||
|
||||
// Force a dimension
|
||||
if (aDimension != null)
|
||||
{
|
||||
tmpB.setMinimumSize(aDimension);
|
||||
tmpB.setMaximumSize(aDimension);
|
||||
tmpB.setPreferredSize(aDimension);
|
||||
}
|
||||
|
||||
return tmpB;
|
||||
}
|
||||
|
||||
public static JButton createJButton(Icon aIcon, ActionListener aActionListener)
|
||||
{
|
||||
return createJButton(aIcon, aActionListener, null);
|
||||
}
|
||||
|
||||
public static JButton createJButton(Icon aIcon, ActionListener aActionListener, String aToolTip)
|
||||
{
|
||||
JButton tmpB;
|
||||
|
||||
tmpB = new JButton(aIcon);
|
||||
tmpB.addActionListener(aActionListener);
|
||||
|
||||
if (aToolTip != null)
|
||||
tmpB.setToolTipText(aToolTip);
|
||||
|
||||
return tmpB;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the JButton with the specified resource icon.
|
||||
*/
|
||||
public static JButton createJButtonViaResource(ActionListener aHandler, String aResourcePath)
|
||||
{
|
||||
return createJButtonViaResource(aHandler, aResourcePath, null);
|
||||
}
|
||||
|
||||
public static JButton createJButtonViaResource(ActionListener aHandler, String aResourcePath, String aToolTip)
|
||||
{
|
||||
JButton tmpB;
|
||||
|
||||
tmpB = new JButton(IconUtil.loadIcon(aResourcePath));
|
||||
tmpB.addActionListener(aHandler);
|
||||
|
||||
if (aToolTip != null)
|
||||
tmpB.setToolTipText(aToolTip);
|
||||
|
||||
return tmpB;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a JCheckBox with the specified settings
|
||||
*/
|
||||
public static JCheckBox createJCheckBox(String aTitle, ActionListener aActionListener)
|
||||
{
|
||||
return createJCheckBox(aTitle, aActionListener, null);
|
||||
}
|
||||
|
||||
public static JCheckBox createJCheckBox(String aTitle, ActionListener aActionListener, Font aFont)
|
||||
{
|
||||
JCheckBox tmpCB;
|
||||
|
||||
tmpCB = new JCheckBox(aTitle);
|
||||
tmpCB.addActionListener(aActionListener);
|
||||
if (aFont != null)
|
||||
tmpCB.setFont(aFont);
|
||||
|
||||
return tmpCB;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a JComboBox with the specified settings
|
||||
*/
|
||||
public static JComboBox createJComboBox(ActionListener aListener, Font aFont, Object... itemArr)
|
||||
{
|
||||
JComboBox tmpBox;
|
||||
|
||||
tmpBox = new JComboBox();
|
||||
for (Object aItem : itemArr)
|
||||
tmpBox.addItem(aItem);
|
||||
|
||||
if (aFont != null)
|
||||
tmpBox.setFont(aFont);
|
||||
|
||||
tmpBox.addActionListener(aListener);
|
||||
return tmpBox;
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Creates a JComboBox with the specified settings
|
||||
// */
|
||||
// public static JComboBox createJComboBox(ActionListener aListener, Object... itemArr)
|
||||
// {
|
||||
// return createJComboBox(aListener, null, itemArr);
|
||||
// }
|
||||
|
||||
/**
|
||||
* Creates a JLabel with the specified settings
|
||||
*/
|
||||
public static JLabel createJLabel(String aTitle, Font aFont)
|
||||
{
|
||||
return createJLabel(aTitle, JLabel.LEADING, aFont);
|
||||
}
|
||||
|
||||
public static JLabel createJLabel(String aTitle, int aAlignment, Font aFont)
|
||||
{
|
||||
JLabel tmpL;
|
||||
|
||||
tmpL = new JLabel(aTitle, aAlignment);
|
||||
|
||||
if (aFont != null)
|
||||
tmpL.setFont(aFont);
|
||||
|
||||
return tmpL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the JRadioButton with the following attributes.
|
||||
*/
|
||||
public static JRadioButton createJRadioButton(String aLabel, ActionListener aListener)
|
||||
{
|
||||
return createJRadioButton(aLabel, aListener, null);
|
||||
}
|
||||
|
||||
public static JRadioButton createJRadioButton(String aLabel, ActionListener aListener, Font aFont)
|
||||
{
|
||||
JRadioButton tmpRB;
|
||||
|
||||
tmpRB = new JRadioButton(aLabel);
|
||||
tmpRB.addActionListener(aListener);
|
||||
if (aFont != null)
|
||||
tmpRB.setFont(aFont);
|
||||
|
||||
return tmpRB;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method for creating a visual thin divider
|
||||
*
|
||||
* Typically added to MigLayout (or like manager) with: add(aComp, "growx,h 4!,span,wrap");
|
||||
*/
|
||||
public static JPanel createDivider()
|
||||
{
|
||||
JPanel tmpPanel;
|
||||
|
||||
tmpPanel = new JPanel();
|
||||
tmpPanel.setBorder(new BevelBorder(BevelBorder.RAISED));
|
||||
|
||||
return tmpPanel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an uneditable JTextArea with no border, non-opaque, line wrap enabled and word wrap enabled.
|
||||
*/
|
||||
public static JTextArea createUneditableTextArea(int rows, int cols)
|
||||
{
|
||||
JTextArea tmpTA;
|
||||
|
||||
tmpTA = new JTextArea("", rows, cols);
|
||||
tmpTA.setEditable(false);
|
||||
tmpTA.setOpaque(false);
|
||||
tmpTA.setLineWrap(true);
|
||||
tmpTA.setWrapStyleWord(true);
|
||||
|
||||
return tmpTA;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an uneditable JTextPane configured with non-opaque and content type of text/html.
|
||||
*/
|
||||
public static JTextPane createUneditableTextPane()
|
||||
{
|
||||
JTextPane tmpTP;
|
||||
|
||||
tmpTP = new JTextPane();
|
||||
tmpTP.setEditable(false);
|
||||
tmpTP.setOpaque(false);
|
||||
tmpTP.setContentType("text/html");
|
||||
|
||||
return tmpTP;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an uneditable JTextField
|
||||
*/
|
||||
public static JTextField createUneditableTextField(String aTitle)
|
||||
{
|
||||
JTextField tmpTF;
|
||||
|
||||
tmpTF = new JTextField(aTitle);
|
||||
tmpTF.setBorder(null);
|
||||
tmpTF.setEditable(false);
|
||||
tmpTF.setOpaque(false);
|
||||
|
||||
return tmpTF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to link a set of radio buttons together
|
||||
*/
|
||||
public static void linkRadioButtons(JRadioButton... buttonArr)
|
||||
{
|
||||
ButtonGroup tmpGroup;
|
||||
|
||||
tmpGroup = new ButtonGroup();
|
||||
for (JRadioButton aItem : buttonArr)
|
||||
tmpGroup.add(aItem);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a boolean from a string with out throwing a exception
|
||||
*/
|
||||
public static boolean readBoolean(String aStr, boolean aVal)
|
||||
{
|
||||
if (aStr == null)
|
||||
return aVal;
|
||||
|
||||
// Special case for 1 char strings
|
||||
if (aStr.length() == 1)
|
||||
{
|
||||
char aChar;
|
||||
|
||||
aChar = aStr.charAt(0);
|
||||
if (aChar == 'T' || aChar == 't' || aChar == '1')
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return Boolean.valueOf(aStr).booleanValue();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
return aVal;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a double from a string with out throwing a exception. Note aStr can have an number of separators: comma
|
||||
* chars
|
||||
*/
|
||||
public static double readDouble(String aStr, double aVal)
|
||||
{
|
||||
try
|
||||
{
|
||||
aStr = aStr.replace(",", "");
|
||||
return Double.parseDouble(aStr);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
return aVal;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a float from a string with out throwing a exception. Note aStr can have an number of separators: comma chars
|
||||
*/
|
||||
public static float readFloat(String aStr, float aVal)
|
||||
{
|
||||
try
|
||||
{
|
||||
aStr = aStr.replace(",", "");
|
||||
return Float.parseFloat(aStr);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
return aVal;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads an int from a string without throwing a exception Note aStr can have an number of separators: comma chars
|
||||
*/
|
||||
public static int readInt(String aStr, int aVal)
|
||||
{
|
||||
try
|
||||
{
|
||||
aStr = aStr.replace(",", "");
|
||||
return Integer.parseInt(aStr);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
return aVal;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a long from a string without throwing a exception Note aStr can have an number of separators: comma chars
|
||||
*/
|
||||
public static long readLong(String aStr, long aVal)
|
||||
{
|
||||
try
|
||||
{
|
||||
aStr = aStr.replace(",", "");
|
||||
return Long.parseLong(aStr);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
return aVal;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads an int (forced to fit within a range) from a string with out throwing a exception
|
||||
*/
|
||||
public static int readRangeInt(String aStr, int minVal, int maxVal, int aVal)
|
||||
{
|
||||
int aInt;
|
||||
|
||||
try
|
||||
{
|
||||
aInt = Integer.parseInt(aStr);
|
||||
if (aInt < minVal)
|
||||
aInt = minVal;
|
||||
else if (aInt > maxVal)
|
||||
aInt = maxVal;
|
||||
|
||||
return aInt;
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
return aVal;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to locate the RootPaneContainer for the specified Component
|
||||
*/
|
||||
public static RootPaneContainer getRootPaneContainer(Component aComponent)
|
||||
{
|
||||
Container aParent;
|
||||
|
||||
// Check to see if the Component is an actual RootPaneContainer
|
||||
if (aComponent instanceof RootPaneContainer)
|
||||
return (RootPaneContainer)aComponent;
|
||||
|
||||
// Attempt to locate the RootPaneContainer (through our stack)
|
||||
aParent = aComponent.getParent();
|
||||
while (aParent != null && (aParent instanceof RootPaneContainer) == false)
|
||||
aParent = aParent.getParent();
|
||||
|
||||
// Bail if we failed to find the RootPaneContainer
|
||||
if (aParent instanceof RootPaneContainer == false)
|
||||
throw new RuntimeException("No valid (grand)parent associated with GlassPane.");
|
||||
|
||||
return (RootPaneContainer)aParent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to locate all of the subcomponents contained in aContainer which are an instance of searchClass
|
||||
*/
|
||||
public static void locateAllSubComponents(Container aContainer, Collection<Component> itemList, Class<?>... searchClassArr)
|
||||
{
|
||||
for (Component aComponent : aContainer.getComponents())
|
||||
{
|
||||
for (Class<?> aClass : searchClassArr)
|
||||
{
|
||||
if (aClass.isInstance(aComponent) == true)
|
||||
{
|
||||
itemList.add(aComponent);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (aComponent instanceof Container)
|
||||
locateAllSubComponents((Container)aComponent, itemList, searchClassArr);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to force a Component to act as modal while it is visible Source:
|
||||
* http://stackoverflow.com/questions/804023/how-do-i-simulate-a-modal-dialog-from-within-an-applet
|
||||
*/
|
||||
public static void modalWhileVisible(Component aComponent)
|
||||
{
|
||||
// Bail if not called from the EventDispatchThread
|
||||
if (SwingUtilities.isEventDispatchThread() == false)
|
||||
throw new RuntimeException("Visibility for modal components must be changed via the Event thread.");
|
||||
|
||||
synchronized(aComponent)
|
||||
{
|
||||
try
|
||||
{
|
||||
EventQueue theQueue = aComponent.getToolkit().getSystemEventQueue();
|
||||
while (aComponent.isVisible())
|
||||
{
|
||||
//System.out.println("About to dispatch event... component.isVisible():" + aComponent.isVisible());
|
||||
AWTEvent event = theQueue.getNextEvent();
|
||||
Object source = event.getSource();
|
||||
if (event instanceof ActiveEvent)
|
||||
{
|
||||
((ActiveEvent)event).dispatch();
|
||||
}
|
||||
else if (source instanceof Component)
|
||||
{
|
||||
((Component)source).dispatchEvent(event);
|
||||
}
|
||||
else if (source instanceof MenuComponent)
|
||||
{
|
||||
((MenuComponent)source).dispatchEvent(event);
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("Unable to dispatch: " + event);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(InterruptedException ignored)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility to call a specific method (methodName) with specific parameters (aParamArr) on aComp and on all of the
|
||||
* child subcomponents. The method will only be called if the components are an instance of refMatchClass.
|
||||
* <P>
|
||||
* This is useful so that a component and all of its children can be disabled, hidden, etc<BR>
|
||||
* Example: GuiUtil.callMethod(myPanel, setEnabled, false);
|
||||
* <P>
|
||||
* Be aware, this is rather expensive, so do not call in time critical applications.
|
||||
*/
|
||||
public static void callMethod(Component aComp, Class<?> refMatchClass, String aMethodName, Object... aParamArr)
|
||||
{
|
||||
Class<?>[] typeArr;
|
||||
|
||||
// Construct the associated type array
|
||||
typeArr = new Class[0];
|
||||
if (aParamArr.length > 0)
|
||||
{
|
||||
// Determine the types of the specified arguments
|
||||
typeArr = new Class[aParamArr.length];
|
||||
for (int c1 = 0; c1 < typeArr.length; c1++)
|
||||
{
|
||||
typeArr[c1] = null;
|
||||
if (aParamArr[c1] != null)
|
||||
typeArr[c1] = aParamArr[c1].getClass();
|
||||
}
|
||||
}
|
||||
|
||||
// Call the helper version
|
||||
callMethodHelper(aComp, refMatchClass, aMethodName, typeArr, aParamArr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to callMethod
|
||||
*/
|
||||
private static void callMethodHelper(Component aComp, Class<?> refMatchClass, String aMethodName, Class<?>[] aTypeArr, Object[] aParamArr)
|
||||
{
|
||||
Component[] subCompArr;
|
||||
Function aFunction;
|
||||
|
||||
// Locate and call the actual method
|
||||
if (refMatchClass.isInstance(aComp) == true)
|
||||
{
|
||||
try
|
||||
{
|
||||
aFunction = new Function(aComp, aMethodName, aTypeArr);
|
||||
aFunction.invoke(aParamArr);
|
||||
}
|
||||
catch(NoSuchMethodException aExp1)
|
||||
{
|
||||
throw new RuntimeException("Failed to locate valid function. Method:" + aMethodName, aExp1);
|
||||
}
|
||||
catch(Exception aExp2)
|
||||
{
|
||||
throw new RuntimeException("Failed to execute function. Method:" + aMethodName, aExp2);
|
||||
}
|
||||
}
|
||||
|
||||
// Bail if we do not have subcomponents
|
||||
if (aComp instanceof Container == false)
|
||||
return;
|
||||
|
||||
// Recurse down our children
|
||||
subCompArr = ((Container)aComp).getComponents();
|
||||
for (Component aSubComp : subCompArr)
|
||||
callMethodHelper(aSubComp, refMatchClass, aMethodName, aTypeArr, aParamArr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to set all subcomponents to the specified enabled mode.
|
||||
*/
|
||||
// TODO: Phase this method out, replace with callMethod()
|
||||
public static void setEnabled(Component aComp, boolean aBool)
|
||||
{
|
||||
Component[] subCompArr;
|
||||
|
||||
aComp.setEnabled(aBool);
|
||||
if (aComp instanceof Container == false)
|
||||
return;
|
||||
|
||||
subCompArr = ((Container)aComp).getComponents();
|
||||
for (Component aSubComp : subCompArr)
|
||||
GuiUtil.setEnabled(aSubComp, aBool);
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to set the enabled switch on all of the specified components.
|
||||
*/
|
||||
public static void setEnabled(boolean aBool, Component... componentArr)
|
||||
{
|
||||
for (Component aComp : componentArr)
|
||||
aComp.setEnabled(aBool);
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method that will call doClick() on the selected RadioButton
|
||||
*/
|
||||
public static void doClickSelectedButton(JRadioButton... buttonArr)
|
||||
{
|
||||
for (int c1 = 0; c1 < buttonArr.length; c1++)
|
||||
{
|
||||
if (buttonArr[c1].isSelected() == true)
|
||||
buttonArr[c1].doClick();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method that takes up to 8 buttons and converts all of their selection states to a single byte.
|
||||
*/
|
||||
public static byte getSelectionStateAsByte(AbstractButton... buttonArr)
|
||||
{
|
||||
byte retByte;
|
||||
|
||||
if (buttonArr.length > 8)
|
||||
throw new RuntimeException("Improper API call. Max of 8 buttons supported. Passed: " + buttonArr.length);
|
||||
|
||||
retByte = 0;
|
||||
for (int c1 = 0; c1 < buttonArr.length; c1++)
|
||||
{
|
||||
if (buttonArr[c1].isSelected() == true)
|
||||
retByte |= 1 << c1;
|
||||
}
|
||||
|
||||
return retByte;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method that takes up to 8 buttons and configures the selection state of the buttons to match the bit
|
||||
* pattern of aByte.
|
||||
*/
|
||||
public static void setSelectionState(byte aByte, AbstractButton... buttonArr)
|
||||
{
|
||||
boolean aBool;
|
||||
|
||||
if (buttonArr.length > 8)
|
||||
throw new RuntimeException("Improper API call. Max of 8 buttons supported. Passed: " + buttonArr.length);
|
||||
|
||||
for (int c1 = 0; c1 < buttonArr.length; c1++)
|
||||
{
|
||||
aBool = false;
|
||||
if (((0x01 << c1) & aByte) != 0)
|
||||
aBool = true;
|
||||
|
||||
buttonArr[c1].setSelected(aBool);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to update a JSlider without triggering notifications to its registered listeners.
|
||||
*/
|
||||
public static void updateSlider(JSlider aSlider, int aVal)
|
||||
{
|
||||
ChangeListener[] tmpArr;
|
||||
|
||||
tmpArr = aSlider.getChangeListeners();
|
||||
|
||||
for (ChangeListener aListener : tmpArr)
|
||||
aSlider.removeChangeListener(aListener);
|
||||
|
||||
aSlider.setValue(aVal);
|
||||
|
||||
for (ChangeListener aListener : tmpArr)
|
||||
aSlider.addChangeListener(aListener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method that checks to ensure the current thread is running on the ATW thread. If it is NOT then the
|
||||
* specified function will be posted so that it is called on the AWT thread. If it is running on the AWT thread then
|
||||
* nothing will happen and this method will return false.
|
||||
* <P>
|
||||
* Typically this utility method is called at the start of a function to ensure it is on the AWT thread, and if not
|
||||
* then schedule the function onto the AWT thread. Thus it is strongly advisable that if this method returns true the
|
||||
* caller should immediately exit.
|
||||
* <P>
|
||||
* <B>Typical usage within a method:</B>
|
||||
*
|
||||
* <PRE>
|
||||
* public void actionPerformed(aEvent)
|
||||
* {
|
||||
* // Ensure this method is run on the AWT thread
|
||||
* if (redispatchOnAwtIfNeeded(this, "actionPerformed", aEvent) = true)
|
||||
* return;
|
||||
*
|
||||
* // Do normal work ...
|
||||
* }
|
||||
* </PRE>
|
||||
*/
|
||||
public static boolean redispatchOnAwtIfNeeded(Object aObj, String methodName, Object... aArgArr)
|
||||
{
|
||||
FunctionRunnable aFunctionRunnable;
|
||||
|
||||
// Do nothing if this is the AWT thread
|
||||
if (SwingUtilities.isEventDispatchThread() == true)
|
||||
return false;
|
||||
|
||||
aFunctionRunnable = new FunctionRunnable(aObj, methodName, aArgArr);
|
||||
SwingUtilities.invokeLater(aFunctionRunnable);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
22
src/glum/gui/action/ClickAction.java
Normal file
22
src/glum/gui/action/ClickAction.java
Normal file
@@ -0,0 +1,22 @@
|
||||
package glum.gui.action;
|
||||
|
||||
import java.awt.event.*;
|
||||
import javax.swing.*;
|
||||
|
||||
public class ClickAction extends AbstractAction
|
||||
{
|
||||
// State vars
|
||||
protected AbstractButton target;
|
||||
|
||||
public ClickAction(AbstractButton aTarget)
|
||||
{
|
||||
target = aTarget;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e)
|
||||
{
|
||||
target.doClick();
|
||||
}
|
||||
|
||||
}
|
||||
23
src/glum/gui/action/MakeVisibleAction.java
Normal file
23
src/glum/gui/action/MakeVisibleAction.java
Normal file
@@ -0,0 +1,23 @@
|
||||
package glum.gui.action;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import javax.swing.*;
|
||||
|
||||
public class MakeVisibleAction extends AbstractAction
|
||||
{
|
||||
// State vars
|
||||
protected Component target;
|
||||
|
||||
public MakeVisibleAction(Component aTarget)
|
||||
{
|
||||
target = aTarget;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e)
|
||||
{
|
||||
target.setVisible(true);
|
||||
}
|
||||
|
||||
}
|
||||
171
src/glum/gui/component/GComboBox.java
Normal file
171
src/glum/gui/component/GComboBox.java
Normal file
@@ -0,0 +1,171 @@
|
||||
package glum.gui.component;
|
||||
|
||||
import glum.gui.component.model.GComboBoxModel;
|
||||
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.*;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.ListCellRenderer;
|
||||
|
||||
public class GComboBox<G1> extends JComboBox
|
||||
{
|
||||
// State vars
|
||||
protected GComboBoxModel<G1> itemModel;
|
||||
|
||||
public GComboBox()
|
||||
{
|
||||
itemModel = new GComboBoxModel<G1>(new LinkedList<G1>());
|
||||
setModel(itemModel);
|
||||
}
|
||||
|
||||
public GComboBox(ActionListener aListener, ListCellRenderer aRenderer)
|
||||
{
|
||||
this();
|
||||
|
||||
addActionListener(aListener);
|
||||
setRenderer(aRenderer);
|
||||
}
|
||||
|
||||
public GComboBox(ActionListener aListener)
|
||||
{
|
||||
this();
|
||||
|
||||
addActionListener(aListener);
|
||||
}
|
||||
|
||||
public GComboBox(ActionListener aListener, List<G1> aItemList)
|
||||
{
|
||||
itemModel = new GComboBoxModel<G1>(aItemList);
|
||||
setModel(itemModel);
|
||||
|
||||
addActionListener(aListener);
|
||||
}
|
||||
|
||||
public GComboBox(ActionListener aListener, G1... aItemArr)
|
||||
{
|
||||
itemModel = new GComboBoxModel<G1>(aItemArr);
|
||||
setModel(itemModel);
|
||||
|
||||
addActionListener(aListener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of all items stored in the GComboBox
|
||||
*/
|
||||
public ArrayList<G1> getAllItems()
|
||||
{
|
||||
return itemModel.getAllItems();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the items that is currently selected.
|
||||
*/
|
||||
public G1 getChosenItem()
|
||||
{
|
||||
return itemModel.getSelectedItem();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets in the currently selected item. This method will not trigger an ActionEvent.
|
||||
* @see JComboBox#setSelectedItem
|
||||
*/
|
||||
public void setChosenItem(G1 aItem)
|
||||
{
|
||||
ActionListener[] listenerArr;
|
||||
|
||||
listenerArr = getActionListeners();
|
||||
for (ActionListener aListener : listenerArr)
|
||||
removeActionListener(aListener);
|
||||
|
||||
itemModel.setSelectedItem(aItem);
|
||||
|
||||
for (ActionListener aListener : listenerArr)
|
||||
addActionListener(aListener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Note aItem must be of the generified type. This method will not trigger an ActionEvent.
|
||||
*/
|
||||
@Override @SuppressWarnings("unchecked")
|
||||
public void addItem(Object aItem)
|
||||
{
|
||||
ActionListener[] listenerArr;
|
||||
|
||||
listenerArr = getActionListeners();
|
||||
for (ActionListener aListener : listenerArr)
|
||||
removeActionListener(aListener);
|
||||
|
||||
itemModel.addItem((G1)aItem);
|
||||
|
||||
for (ActionListener aListener : listenerArr)
|
||||
addActionListener(aListener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Note aItem must be of the generified type. This method will not trigger an ActionEvent.
|
||||
*/
|
||||
public void addItems(G1... aItemArr)
|
||||
{
|
||||
ActionListener[] listenerArr;
|
||||
|
||||
listenerArr = getActionListeners();
|
||||
for (ActionListener aListener : listenerArr)
|
||||
removeActionListener(aListener);
|
||||
|
||||
for (G1 aItem : aItemArr)
|
||||
itemModel.addItem(aItem);
|
||||
|
||||
for (ActionListener aListener : listenerArr)
|
||||
addActionListener(aListener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Note aItem must be of the generified type. This method will not trigger an ActionEvent.
|
||||
*/
|
||||
@Override @SuppressWarnings("unchecked")
|
||||
public void removeItem(Object aItem)
|
||||
{
|
||||
ActionListener[] listenerArr;
|
||||
|
||||
listenerArr = getActionListeners();
|
||||
for (ActionListener aListener : listenerArr)
|
||||
removeActionListener(aListener);
|
||||
|
||||
itemModel.removeItem((G1)aItem);
|
||||
|
||||
for (ActionListener aListener : listenerArr)
|
||||
addActionListener(aListener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all of the items from the model. This method will not trigger an ActionEvent.
|
||||
*/
|
||||
@Override
|
||||
public void removeAllItems()
|
||||
{
|
||||
ActionListener[] listenerArr;
|
||||
|
||||
listenerArr = getActionListeners();
|
||||
for (ActionListener aListener : listenerArr)
|
||||
removeActionListener(aListener);
|
||||
|
||||
itemModel.removeAllItems();
|
||||
|
||||
for (ActionListener aListener : listenerArr)
|
||||
addActionListener(aListener);
|
||||
}
|
||||
|
||||
// Note you cannot do the below as internal methods within JComboBox make calls to
|
||||
// the methods below.
|
||||
// @Override
|
||||
// public Object getSelectedItem()
|
||||
// {
|
||||
// throw new RuntimeException("Unsupported operation. Call getChosenItem()");
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void setSelectedItem(Object aObj)
|
||||
// {
|
||||
// throw new RuntimeException("Unsupported operation. Call setChosenItem()");
|
||||
// }
|
||||
}
|
||||
49
src/glum/gui/component/GComponent.java
Normal file
49
src/glum/gui/component/GComponent.java
Normal file
@@ -0,0 +1,49 @@
|
||||
package glum.gui.component;
|
||||
|
||||
import glum.gui.panel.generic.GenericCodes;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.List;
|
||||
import javax.swing.JComponent;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
public class GComponent extends JComponent implements GenericCodes
|
||||
{
|
||||
// State vars
|
||||
protected List<ActionListener> myListeners;
|
||||
|
||||
public GComponent()
|
||||
{
|
||||
super();
|
||||
|
||||
myListeners = Lists.newLinkedList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an ActionListener to this GPanel
|
||||
*/
|
||||
public void addActionListener(ActionListener aListener)
|
||||
{
|
||||
myListeners.add(aListener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an ActionListener to this GPanel
|
||||
*/
|
||||
public void removeActionListener(ActionListener aListener)
|
||||
{
|
||||
myListeners.remove(aListener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send out notification to all of the ActionListeners
|
||||
*/
|
||||
public void notifyListeners(Object aSource, int aId, String aCommand)
|
||||
{
|
||||
for (ActionListener aListener : myListeners)
|
||||
aListener.actionPerformed(new ActionEvent(aSource, aId, aCommand));
|
||||
}
|
||||
|
||||
}
|
||||
93
src/glum/gui/component/GFancyLabel.java
Normal file
93
src/glum/gui/component/GFancyLabel.java
Normal file
@@ -0,0 +1,93 @@
|
||||
package glum.gui.component;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Font;
|
||||
|
||||
import glum.unit.UnitListener;
|
||||
import glum.unit.UnitProvider;
|
||||
|
||||
import javax.swing.JLabel;
|
||||
|
||||
public class GFancyLabel extends JLabel implements UnitListener
|
||||
{
|
||||
// State vars
|
||||
protected UnitProvider[] unitProviderArr;
|
||||
protected String[] formatStrArr;
|
||||
protected Object[] refValueArr;
|
||||
|
||||
/**
|
||||
* Fancy JLabel which provides auto formatting of objects. The constructor
|
||||
* is provided with a formatStr which has unit place holders specified by "%u"
|
||||
* There must be a corresponding UnitProvider for each occurrence of "%u". This
|
||||
* is provided via the variable arguments of UnitProvider.
|
||||
*/
|
||||
public GFancyLabel(String formatStr, UnitProvider... aUnitProviderArr)
|
||||
{
|
||||
this(null, formatStr, aUnitProviderArr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fancy JLabel which provides auto formatting of objects. The constructor
|
||||
* is provided with a formatStr which has unit place holders specified by "%u"
|
||||
* There must be a corresponding UnitProvider for each occurrence of "%u". This
|
||||
* is provided via the variable arguments of UnitProvider.
|
||||
*/
|
||||
public GFancyLabel(Font aFont, String aFormatStr, UnitProvider... aUnitProviderArr)
|
||||
{
|
||||
super();
|
||||
|
||||
if (aFont != null)
|
||||
setFont(aFont);
|
||||
|
||||
formatStrArr = aFormatStr.split("%u", -1);
|
||||
|
||||
unitProviderArr = aUnitProviderArr;
|
||||
for (UnitProvider aUnitProvider : unitProviderArr)
|
||||
aUnitProvider.addListener(this);
|
||||
|
||||
// Insanity check
|
||||
if (unitProviderArr.length != formatStrArr.length - 1)
|
||||
throw new RuntimeException("Num place holders: " + (formatStrArr.length - 1) + " Num units: " + unitProviderArr.length);
|
||||
|
||||
refValueArr = new Object[unitProviderArr.length];
|
||||
for (int c1 = 0; c1 < unitProviderArr.length; c1++)
|
||||
refValueArr[c1] = null;
|
||||
|
||||
setMinimumSize(new Dimension(0, 0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unitChanged(UnitProvider aProvider, String aKey)
|
||||
{
|
||||
setValues(refValueArr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to set in the set of values which will be formatted with the associated UnitProviders
|
||||
* which were specified via the constructor.
|
||||
*/
|
||||
public void setValues(Object... aValueArr)
|
||||
{
|
||||
String aStr;
|
||||
|
||||
// Ensure the number of objects matches the number of units
|
||||
if (unitProviderArr.length != aValueArr.length)
|
||||
throw new RuntimeException("Inproper number of arguments. Expected: " + unitProviderArr.length + " Recieved:" + aValueArr.length);
|
||||
|
||||
for (int c1 = 0; c1 < aValueArr.length; c1++)
|
||||
refValueArr[c1] = aValueArr[c1];
|
||||
|
||||
aStr = "";
|
||||
for (int c1 = 0; c1 < aValueArr.length; c1++)
|
||||
{
|
||||
aStr += formatStrArr[c1];
|
||||
aStr += unitProviderArr[c1].getUnit().getString(aValueArr[c1], false);
|
||||
}
|
||||
|
||||
if (formatStrArr.length > aValueArr.length)
|
||||
aStr += formatStrArr[formatStrArr.length - 1];
|
||||
|
||||
setText(aStr);
|
||||
}
|
||||
|
||||
}
|
||||
82
src/glum/gui/component/GLabel.java
Normal file
82
src/glum/gui/component/GLabel.java
Normal file
@@ -0,0 +1,82 @@
|
||||
package glum.gui.component;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Font;
|
||||
|
||||
import glum.unit.ConstUnitProvider;
|
||||
import glum.unit.Unit;
|
||||
import glum.unit.UnitListener;
|
||||
import glum.unit.UnitProvider;
|
||||
|
||||
import javax.swing.JLabel;
|
||||
|
||||
public class GLabel extends JLabel implements UnitListener
|
||||
{
|
||||
// State vars
|
||||
protected UnitProvider refUnitProvider;
|
||||
protected Object refValue;
|
||||
protected boolean showLabel;
|
||||
|
||||
public GLabel(Font aFont)
|
||||
{
|
||||
this(null, aFont, false);
|
||||
}
|
||||
|
||||
public GLabel(Unit aUnit, Font aFont)
|
||||
{
|
||||
this(new ConstUnitProvider(aUnit), aFont, false);
|
||||
}
|
||||
|
||||
public GLabel(UnitProvider aUnitProvider, Font aFont)
|
||||
{
|
||||
this(aUnitProvider, aFont, false);
|
||||
}
|
||||
|
||||
public GLabel(UnitProvider aUnitProvider, Font aFont, boolean aShowLabel)
|
||||
{
|
||||
super();
|
||||
|
||||
refUnitProvider = aUnitProvider;
|
||||
if (refUnitProvider != null)
|
||||
refUnitProvider.addListener(this);
|
||||
refValue = null;
|
||||
|
||||
if (aFont != null)
|
||||
setFont(aFont);
|
||||
|
||||
showLabel = aShowLabel;
|
||||
|
||||
setMinimumSize(new Dimension(0, 0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unitChanged(UnitProvider aProvider, String aKey)
|
||||
{
|
||||
setValue(refValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to set in the value which will be formatted with the associated unit.
|
||||
*/
|
||||
public void setValue(Object aValue)
|
||||
{
|
||||
String aStr;
|
||||
Unit aUnit;
|
||||
|
||||
refValue = aValue;
|
||||
|
||||
aUnit = null;
|
||||
if (refUnitProvider != null)
|
||||
aUnit = refUnitProvider.getUnit();
|
||||
|
||||
if (aUnit == null)
|
||||
aStr = "" + aValue;
|
||||
else if (showLabel == false)
|
||||
aStr = aUnit.getString(aValue);
|
||||
else
|
||||
aStr = aUnit.getString(aValue, true);
|
||||
|
||||
setText(aStr);
|
||||
}
|
||||
|
||||
}
|
||||
159
src/glum/gui/component/GList.java
Normal file
159
src/glum/gui/component/GList.java
Normal file
@@ -0,0 +1,159 @@
|
||||
package glum.gui.component;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.event.ListSelectionEvent;
|
||||
import javax.swing.event.ListSelectionListener;
|
||||
|
||||
import glum.gui.component.model.GListModel;
|
||||
import glum.gui.panel.generic.GenericCodes;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
public class GList<G1> extends JComponent implements GenericCodes, ListSelectionListener
|
||||
{
|
||||
// Gui vars
|
||||
private JList refList;
|
||||
private GListModel<G1> refModel;
|
||||
|
||||
// State vars
|
||||
private ActionListener refActionListener;
|
||||
private ListSelectionListener refListSelectionListener;
|
||||
|
||||
public GList(Object aListener, List<G1> aItemList)
|
||||
{
|
||||
refActionListener = null;
|
||||
refListSelectionListener = null;
|
||||
|
||||
refModel = new GListModel<G1>(aItemList);
|
||||
refList = new JList(refModel);
|
||||
buildGui(aListener);
|
||||
}
|
||||
|
||||
public GList(Object aListener, G1... aItemArr)
|
||||
{
|
||||
refActionListener = null;
|
||||
refListSelectionListener = null;
|
||||
|
||||
refModel = new GListModel<G1>(aItemArr);
|
||||
refList = new JList(refModel);
|
||||
buildGui(aListener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the (first) selected item
|
||||
*/
|
||||
public G1 getSelectedItem()
|
||||
{
|
||||
int selectedIndex;
|
||||
|
||||
selectedIndex = refList.getSelectedIndex();
|
||||
if (selectedIndex == -1)
|
||||
return null;
|
||||
|
||||
return refModel.getElementAt(selectedIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all of the selected items
|
||||
*/
|
||||
public List<G1> getSelectedItems()
|
||||
{
|
||||
ArrayList<G1> retList;
|
||||
int[] indexArr;
|
||||
|
||||
indexArr = refList.getSelectedIndices();
|
||||
|
||||
retList = Lists.newArrayList();
|
||||
for (int aIndex : indexArr)
|
||||
retList.add(refModel.getElementAt(aIndex));
|
||||
|
||||
retList.trimToSize();
|
||||
return retList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces all of the items in the list with aItemList.
|
||||
*/
|
||||
public void setItems(Collection<G1> aItemList)
|
||||
{
|
||||
refList.removeListSelectionListener(this);
|
||||
refList.setModel(new GListModel<G1>(aItemList));
|
||||
refList.addListSelectionListener(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets aItem as the selected item.
|
||||
*/
|
||||
public void setSelectedItem(G1 aItem)
|
||||
{
|
||||
refList.removeListSelectionListener(this);
|
||||
refList.setSelectedIndex(refModel.indexOf(aItem));
|
||||
refList.addListSelectionListener(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets all of the items in aItemList as selected
|
||||
*/
|
||||
public void setSelectedItems(List<G1> aItemList)
|
||||
{
|
||||
int[] idArr;
|
||||
int c1;
|
||||
|
||||
// Ensure we are executed only on the proper thread
|
||||
if (SwingUtilities.isEventDispatchThread() == false)
|
||||
throw new RuntimeException("GList.selectItems() not executed on the AWT event dispatch thread.");
|
||||
|
||||
refList.removeListSelectionListener(this);
|
||||
|
||||
c1 = 0;
|
||||
idArr = new int[aItemList.size()];
|
||||
for (G1 aItem : aItemList)
|
||||
{
|
||||
idArr[c1] = refModel.indexOf(aItem);
|
||||
c1++;
|
||||
}
|
||||
|
||||
refList.setSelectedIndices(idArr);
|
||||
|
||||
refList.addListSelectionListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnabled(boolean aBool)
|
||||
{
|
||||
refList.setEnabled(aBool);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void valueChanged(ListSelectionEvent aEvent)
|
||||
{
|
||||
if (refListSelectionListener != null)
|
||||
refListSelectionListener.valueChanged(new ListSelectionEvent(this, aEvent.getFirstIndex(), aEvent.getLastIndex(), aEvent.getValueIsAdjusting()));
|
||||
|
||||
if (refActionListener != null)
|
||||
refActionListener.actionPerformed(new ActionEvent(this, ID_UPDATE, "update"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method used to build the GUI
|
||||
*/
|
||||
private void buildGui(Object aListener)
|
||||
{
|
||||
if (aListener instanceof ActionListener)
|
||||
refActionListener = (ActionListener)aListener;
|
||||
if (aListener instanceof ListSelectionListener)
|
||||
refListSelectionListener = (ListSelectionListener)aListener;
|
||||
|
||||
setLayout(new BorderLayout());
|
||||
add(refList);
|
||||
}
|
||||
|
||||
}
|
||||
298
src/glum/gui/component/GNumberField.java
Normal file
298
src/glum/gui/component/GNumberField.java
Normal file
@@ -0,0 +1,298 @@
|
||||
package glum.gui.component;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.event.ActionListener;
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.*;
|
||||
import javax.swing.text.*;
|
||||
|
||||
import glum.gui.document.NumberDocument;
|
||||
import glum.unit.ConstUnitProvider;
|
||||
import glum.unit.NumberUnit;
|
||||
import glum.unit.Unit;
|
||||
import glum.unit.UnitListener;
|
||||
import glum.unit.UnitProvider;
|
||||
|
||||
public class GNumberField extends JTextField implements DocumentListener, UnitListener
|
||||
{
|
||||
// State vars
|
||||
protected UnitProvider refUnitProvider;
|
||||
protected double currValue, minValue, maxValue;
|
||||
protected boolean isMutating;
|
||||
|
||||
// Gui vars
|
||||
protected Color failColor, passColor;
|
||||
protected NumberDocument myDocument;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param aListener
|
||||
* : Default ActionListener
|
||||
* @param aUnit
|
||||
* : Object used to format programatic entered values. Note aUnitProvider will also be used to determine if
|
||||
* Floating or only Integral input is allowed.
|
||||
* @param inputType
|
||||
* : Type of input to accept (Integer, Double, etc...)
|
||||
* @param aMinVal
|
||||
* : Minimum value to accept
|
||||
* @param aMaxVal
|
||||
* : Maximum value to accept
|
||||
*/
|
||||
public GNumberField(ActionListener aListener, UnitProvider aUnitProvider, double aMinVal, double aMaxVal)
|
||||
{
|
||||
super("", 0);
|
||||
|
||||
refUnitProvider = aUnitProvider;
|
||||
currValue = 0;
|
||||
minValue = aMinVal;
|
||||
maxValue = aMaxVal;
|
||||
isMutating = false;
|
||||
|
||||
failColor = Color.RED.darker();
|
||||
passColor = getForeground();
|
||||
|
||||
// Register the ActionListener
|
||||
if (aListener != null)
|
||||
addActionListener(aListener);
|
||||
|
||||
// Form the appropriate Document and initialize
|
||||
myDocument = new NumberDocument(this, false);
|
||||
super.setDocument(myDocument);
|
||||
|
||||
// Register for events of interest
|
||||
myDocument.addDocumentListener(this);
|
||||
refUnitProvider.addListener(this);
|
||||
|
||||
// Install our unit into the Document. Note this should be done last as the method installUnit() assumes that
|
||||
// this GNumberField is already registered with myDocument (via the method call forceTF()).
|
||||
installUnit();
|
||||
}
|
||||
|
||||
public GNumberField(ActionListener aListener, Unit aUnit, double aMinVal, double aMaxVal)
|
||||
{
|
||||
this(aListener, new ConstUnitProvider(aUnit), aMinVal, aMaxVal);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the current input is valid
|
||||
*/
|
||||
public boolean isValidInput()
|
||||
{
|
||||
Unit aUnit;
|
||||
double modelVal;
|
||||
|
||||
// Ensure we have valid input
|
||||
aUnit = refUnitProvider.getUnit();
|
||||
|
||||
modelVal = aUnit.parseString(this.getText(), Double.NaN);
|
||||
if (Double.isNaN(modelVal) == true)
|
||||
return false;
|
||||
|
||||
// Ensure the value is within range
|
||||
if (modelVal < minValue || modelVal > maxValue)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the currently stored model value to Double.NaN. Also clears out the input area. This method will not trigger
|
||||
* an ActionEvent.
|
||||
*/
|
||||
public void clearValue()
|
||||
{
|
||||
currValue = Double.NaN;
|
||||
|
||||
myDocument.removeDocumentListener(this);
|
||||
setText("");
|
||||
setCaretPosition(0);
|
||||
myDocument.addDocumentListener(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the currently stored model value
|
||||
*/
|
||||
public double getValue()
|
||||
{
|
||||
return currValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the currently stored model value as an integer. If the modelValue is NaN, then errorVal will be returned.
|
||||
* The values MaxInt, MinInt are returned for Infinity.
|
||||
*/
|
||||
public int getValueAsInt(int errorVal)
|
||||
{
|
||||
if (Double.isNaN(currValue) == true)
|
||||
return errorVal;
|
||||
|
||||
return (int)currValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes in a model value and will display it with respect to the active unit. This method will not trigger an
|
||||
* ActionEvent.
|
||||
* <P>
|
||||
* Note this method will do nothing if the UI is being "mutated" when this method is called.
|
||||
*/
|
||||
public void setValue(final double aValue)
|
||||
{
|
||||
// Bail if we are being mutated. The alternative is to throw an exception like:
|
||||
// throw new IllegalStateException("Attempt to mutate in notification");
|
||||
if (isMutating == true)
|
||||
return;
|
||||
|
||||
// Simple edit if we are not currently being mutated
|
||||
forceTF(aValue);
|
||||
updateGui();
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the range of acceptable values (in model units). Note the current value will be force to fit this range.
|
||||
*/
|
||||
public void setMinMaxValue(double aMinValue, double aMaxValue)
|
||||
{
|
||||
Unit aUnit;
|
||||
|
||||
minValue = aMinValue;
|
||||
maxValue = aMaxValue;
|
||||
if (currValue < minValue || currValue > maxValue)
|
||||
currValue = minValue;
|
||||
|
||||
// Update our document
|
||||
aUnit = refUnitProvider.getUnit();
|
||||
myDocument.setMinMaxValue(aUnit.toUnit(minValue), aUnit.toUnit(maxValue));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDocument(Document aDoc)
|
||||
{
|
||||
// throw new UnsupportedOperationException();
|
||||
if (aDoc != null)
|
||||
aDoc.addDocumentListener(this);
|
||||
|
||||
super.setDocument(aDoc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changedUpdate(DocumentEvent aEvent)
|
||||
{
|
||||
syncValue(aEvent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insertUpdate(DocumentEvent aEvent)
|
||||
{
|
||||
syncValue(aEvent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeUpdate(DocumentEvent aEvent)
|
||||
{
|
||||
syncValue(aEvent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unitChanged(UnitProvider aProvider, String aKey)
|
||||
{
|
||||
installUnit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the internal model value and will update the display wrt to the active unit.
|
||||
*/
|
||||
protected void forceTF(double aValue)
|
||||
{
|
||||
Unit aUnit;
|
||||
String aStr;
|
||||
|
||||
// Save off the new model value, and check the validity
|
||||
currValue = aValue;
|
||||
if (currValue < minValue || currValue > maxValue)
|
||||
currValue = Double.NaN;
|
||||
// throw new RuntimeException("Programatic input is invalid. Is unit compatible? Input: " + aValue);
|
||||
|
||||
// Invalid values shall just clear the text field and bail
|
||||
if (Double.isNaN(currValue) == true)
|
||||
{
|
||||
clearValue();
|
||||
return;
|
||||
}
|
||||
|
||||
// Convert from model value to (unit) textual format
|
||||
aUnit = refUnitProvider.getUnit();
|
||||
aStr = aUnit.getString(currValue);
|
||||
|
||||
// Update the GUI internals
|
||||
myDocument.removeDocumentListener(this);
|
||||
setText(aStr);
|
||||
setCaretPosition(0);
|
||||
myDocument.addDocumentListener(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to update the associated Document whenever a Unit is changed
|
||||
*/
|
||||
protected void installUnit()
|
||||
{
|
||||
Unit aUnit;
|
||||
boolean aBool;
|
||||
|
||||
// Ensure that we have a valid Unit
|
||||
aUnit = refUnitProvider.getUnit();
|
||||
if (aUnit instanceof NumberUnit == false)
|
||||
throw new RuntimeException("refUnitProvider must return a Unit of type NumberUnit. Unit: " + aUnit);
|
||||
|
||||
// Update our Document to reflect whether this Unit supports floating point numbers
|
||||
aBool = (aUnit instanceof NumberUnit) && (((NumberUnit)aUnit).isFloating() == true);
|
||||
myDocument.setAllowFloats(aBool);
|
||||
|
||||
// Update the Document's MinMax values reflect the new Unit
|
||||
setMinMaxValue(minValue, maxValue);
|
||||
|
||||
// Force myDocument's text to match the new unit
|
||||
forceTF(currValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Keeps the "model" value conceptually linked to the GUI component. It will also trigger the actionEventListeners.
|
||||
*/
|
||||
protected void syncValue(DocumentEvent e)
|
||||
{
|
||||
Unit aUnit;
|
||||
|
||||
// Mark ourself as mutating
|
||||
isMutating = true;
|
||||
|
||||
// Convert the textual (unit) value to the model value
|
||||
aUnit = refUnitProvider.getUnit();
|
||||
currValue = aUnit.parseString(this.getText(), Double.NaN);
|
||||
|
||||
// If the value is not in range then, it is invalid
|
||||
if (currValue < minValue || currValue > maxValue)
|
||||
currValue = Double.NaN;
|
||||
|
||||
// Notify our listeners and update the GUI
|
||||
updateGui();
|
||||
fireActionPerformed();
|
||||
|
||||
// We are no longer mutating
|
||||
isMutating = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to update the GUI to reflect the current state of the NumberField
|
||||
*/
|
||||
protected void updateGui()
|
||||
{
|
||||
Color aColor;
|
||||
|
||||
aColor = passColor;
|
||||
if (isValidInput() == false)
|
||||
aColor = failColor;
|
||||
|
||||
setForeground(aColor);
|
||||
}
|
||||
|
||||
}
|
||||
106
src/glum/gui/component/GPasswordField.java
Normal file
106
src/glum/gui/component/GPasswordField.java
Normal file
@@ -0,0 +1,106 @@
|
||||
package glum.gui.component;
|
||||
|
||||
import java.awt.event.ActionListener;
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.*;
|
||||
import javax.swing.text.*;
|
||||
|
||||
public class GPasswordField extends JPasswordField implements DocumentListener
|
||||
{
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param aListener
|
||||
* : Default ActionListener
|
||||
*/
|
||||
public GPasswordField(ActionListener aListener)
|
||||
{
|
||||
super("", 0);
|
||||
|
||||
if (aListener != null)
|
||||
addActionListener(aListener);
|
||||
|
||||
// Form the appropriate Document
|
||||
Document doc;
|
||||
doc = new PlainDocument();
|
||||
super.setDocument(doc);
|
||||
|
||||
// Register for events of interest
|
||||
doc.addDocumentListener(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the current input is valid
|
||||
*/
|
||||
public boolean isValidInput()
|
||||
{
|
||||
if (getPassword().length < 2)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets in the value for the GTextField. Note this method will not trigger an ActionEvent.
|
||||
*/
|
||||
public void setValue(String aText)
|
||||
{
|
||||
forceTF(aText);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDocument(Document aDoc)
|
||||
{
|
||||
// throw new UnsupportedOperationException();
|
||||
if (aDoc != null)
|
||||
aDoc.addDocumentListener(this);
|
||||
|
||||
super.setDocument(aDoc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changedUpdate(DocumentEvent aEvent)
|
||||
{
|
||||
fireActionPerformed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insertUpdate(DocumentEvent aEvent)
|
||||
{
|
||||
fireActionPerformed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeUpdate(DocumentEvent aEvent)
|
||||
{
|
||||
fireActionPerformed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the internal model value and will update the display wrt tho active unit.
|
||||
*/
|
||||
protected void forceTF(String aStr)
|
||||
{
|
||||
Document aDocument;
|
||||
|
||||
// Update the GUI internals
|
||||
aDocument = this.getDocument();
|
||||
if (aDocument != null)
|
||||
aDocument.removeDocumentListener(this);
|
||||
|
||||
setText(aStr);
|
||||
setCaretPosition(0);
|
||||
|
||||
if (aDocument != null)
|
||||
aDocument.addDocumentListener(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Keeps the "model" value conceptually linked to the GUI component. It will also trigger the actionEventListeners.
|
||||
*/
|
||||
protected void syncValue(DocumentEvent aEvent)
|
||||
{
|
||||
fireActionPerformed();
|
||||
}
|
||||
|
||||
}
|
||||
91
src/glum/gui/component/GSlider.java
Normal file
91
src/glum/gui/component/GSlider.java
Normal file
@@ -0,0 +1,91 @@
|
||||
package glum.gui.component;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import javax.swing.JSlider;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
|
||||
public class GSlider extends JSlider implements ChangeListener
|
||||
{
|
||||
private ActionListener myListener;
|
||||
private double minVal, maxVal, rngVal;
|
||||
private int maxSteps;
|
||||
|
||||
public GSlider(ActionListener aListener, int aMaxSteps, double aMinVal, double aMaxVal)
|
||||
{
|
||||
super(0, aMaxSteps);
|
||||
addChangeListener(this);
|
||||
|
||||
myListener = aListener;
|
||||
|
||||
maxSteps = aMaxSteps;
|
||||
|
||||
minVal = aMinVal;
|
||||
maxVal = aMaxVal;
|
||||
rngVal = maxVal - minVal;
|
||||
}
|
||||
|
||||
public GSlider(ActionListener aListener, double aMinVal, double aMaxVal)
|
||||
{
|
||||
this(aListener, 1000, aMinVal, aMaxVal);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the model value for which this slider is currently set to.
|
||||
* <P>
|
||||
* Use this method over {@link JSlider#getValue()}
|
||||
*/
|
||||
public double getModelValue()
|
||||
{
|
||||
double retVal;
|
||||
|
||||
retVal = minVal + ((super.getValue() / (double)maxSteps) * rngVal);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes in the model's minVal and maxVal range. The current chosen model value will be adjusted to be in the middle
|
||||
* of the range.
|
||||
*/
|
||||
public void setModelRange(double aMinVal, double aMaxVal)
|
||||
{
|
||||
minVal = aMinVal;
|
||||
maxVal = aMaxVal;
|
||||
rngVal = maxVal - minVal;
|
||||
|
||||
setModelValue(minVal + rngVal / 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes in a model value and will adjust the slider to display the value. Note this method will not trigger an
|
||||
* ActionEvent.
|
||||
* <P>
|
||||
* Use this method over {@link JSlider#setValue}
|
||||
*/
|
||||
public void setModelValue(double aVal)
|
||||
{
|
||||
double guiVal;
|
||||
|
||||
guiVal = ((aVal - minVal) / rngVal) * maxSteps;
|
||||
|
||||
removeChangeListener(this);
|
||||
setValue((int)guiVal);
|
||||
addChangeListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stateChanged(ChangeEvent aEvent)
|
||||
{
|
||||
notifyLisener();
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to notify our listener
|
||||
*/
|
||||
private void notifyLisener()
|
||||
{
|
||||
myListener.actionPerformed(new ActionEvent(this, 0, "update"));
|
||||
}
|
||||
|
||||
}
|
||||
114
src/glum/gui/component/GTextField.java
Normal file
114
src/glum/gui/component/GTextField.java
Normal file
@@ -0,0 +1,114 @@
|
||||
package glum.gui.component;
|
||||
|
||||
import java.awt.event.ActionListener;
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.*;
|
||||
import javax.swing.text.*;
|
||||
|
||||
public class GTextField extends JTextField implements DocumentListener
|
||||
{
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param aListener
|
||||
* : Default ActionListener
|
||||
*/
|
||||
public GTextField(ActionListener aListener)
|
||||
{
|
||||
super("", 0);
|
||||
|
||||
if (aListener != null)
|
||||
addActionListener(aListener);
|
||||
|
||||
// Form the appropriate Document
|
||||
Document doc;
|
||||
doc = new PlainDocument();
|
||||
super.setDocument(doc);
|
||||
|
||||
// Register for events of interest
|
||||
doc.addDocumentListener(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the current input is valid
|
||||
*/
|
||||
public boolean isValidInput()
|
||||
{
|
||||
if (getText().isEmpty() == true)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the currently stored model value
|
||||
*/
|
||||
public String getValue()
|
||||
{
|
||||
return getText();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets in the value for the GTextField. Note this method will not trigger an ActionEvent.
|
||||
*/
|
||||
public void setValue(String aText)
|
||||
{
|
||||
forceTF(aText);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDocument(Document aDoc)
|
||||
{
|
||||
// throw new UnsupportedOperationException();
|
||||
if (aDoc != null)
|
||||
aDoc.addDocumentListener(this);
|
||||
|
||||
super.setDocument(aDoc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changedUpdate(DocumentEvent aEvent)
|
||||
{
|
||||
fireActionPerformed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insertUpdate(DocumentEvent aEvent)
|
||||
{
|
||||
fireActionPerformed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeUpdate(DocumentEvent aEvent)
|
||||
{
|
||||
fireActionPerformed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the internal model value and will update the display wrt tho active unit.
|
||||
*/
|
||||
protected void forceTF(String aStr)
|
||||
{
|
||||
Document aDocument;
|
||||
|
||||
// Update the GUI internals
|
||||
aDocument = this.getDocument();
|
||||
if (aDocument != null)
|
||||
aDocument.removeDocumentListener(this);
|
||||
|
||||
setText(aStr);
|
||||
setCaretPosition(0);
|
||||
|
||||
if (aDocument != null)
|
||||
aDocument.addDocumentListener(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Keeps the "model" value conceptually linked to the GUI component. It will also trigger the actionEventListeners.
|
||||
*/
|
||||
protected void syncValue(DocumentEvent aEvent)
|
||||
{
|
||||
fireActionPerformed();
|
||||
}
|
||||
|
||||
}
|
||||
76
src/glum/gui/component/GToggle.java
Normal file
76
src/glum/gui/component/GToggle.java
Normal file
@@ -0,0 +1,76 @@
|
||||
package glum.gui.component;
|
||||
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.JToggleButton;
|
||||
|
||||
public class GToggle extends JToggleButton
|
||||
{
|
||||
// State vars
|
||||
protected boolean isActive;
|
||||
|
||||
// Gui vars
|
||||
protected Icon falseIcon, trueIcon;
|
||||
|
||||
public GToggle(Icon aFalseIcon, Icon aTrueIcon, boolean aIsActive)
|
||||
{
|
||||
super();
|
||||
|
||||
falseIcon = aFalseIcon;
|
||||
trueIcon = aTrueIcon;
|
||||
setSelected(aIsActive);
|
||||
|
||||
setModel(new GToggleButtonModel());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelected(boolean b)
|
||||
{
|
||||
super.setSelected(b);
|
||||
updateGui();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doClick(int pressTime)
|
||||
{
|
||||
super.doClick(pressTime);
|
||||
updateGui();
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method
|
||||
*/
|
||||
private void updateGui()
|
||||
{
|
||||
if (isSelected() == true)
|
||||
setIcon(trueIcon);
|
||||
else
|
||||
setIcon(falseIcon);
|
||||
}
|
||||
|
||||
/**
|
||||
* The ToggleButton model
|
||||
* <p>
|
||||
* <strong>Warning:</strong> Serialized objects of this class will not be compatible with future Swing releases. The
|
||||
* current serialization support is appropriate for short term storage or RMI between applications running the same
|
||||
* version of Swing. As of 1.4, support for long term storage of all JavaBeans<sup><font size="-2">TM</font></sup>
|
||||
* has been added to the <code>java.beans</code> package. Please see {@link java.beans.XMLEncoder}.
|
||||
*/
|
||||
public class GToggleButtonModel extends ToggleButtonModel
|
||||
{
|
||||
/**
|
||||
* Creates a new ToggleButton Model
|
||||
*/
|
||||
public GToggleButtonModel()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelected(boolean b)
|
||||
{
|
||||
super.setSelected(b);
|
||||
|
||||
updateGui();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
222
src/glum/gui/component/banner/Banner.java
Normal file
222
src/glum/gui/component/banner/Banner.java
Normal file
@@ -0,0 +1,222 @@
|
||||
package glum.gui.component.banner;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.geom.*;
|
||||
import java.util.*;
|
||||
import javax.swing.*;
|
||||
|
||||
import glum.gui.*;
|
||||
import glum.io.token.MatchTokenizer;
|
||||
import glum.io.token.Tokenizer;
|
||||
|
||||
public class Banner extends JComponent
|
||||
{
|
||||
// Our configuration
|
||||
protected BannerConfig myConfig;
|
||||
|
||||
// Current message to display
|
||||
protected String displayMsg;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public Banner()
|
||||
{
|
||||
super();
|
||||
|
||||
myConfig = new BannerConfig();
|
||||
setConfig(myConfig);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintComponent(Graphics g)
|
||||
{
|
||||
Graphics2D g2d;
|
||||
Rectangle2D aRect;
|
||||
double winW, winH, msgW, msgH;
|
||||
double sX, sY, offSetY;
|
||||
|
||||
super.paintComponent(g);
|
||||
g2d = (Graphics2D)g;
|
||||
|
||||
// Determine the window boundaries
|
||||
winW = getWidth();
|
||||
winH = getHeight();
|
||||
|
||||
// Compute the displayMsg boundaries
|
||||
aRect = myConfig.font.getStringBounds(displayMsg, g2d.getFontRenderContext());
|
||||
msgW = aRect.getWidth();
|
||||
msgH = aRect.getHeight();
|
||||
offSetY = msgH - aRect.getMaxY();
|
||||
|
||||
// Form our rectangle
|
||||
aRect = new Rectangle2D.Double(0, 0, winW, winH);
|
||||
|
||||
// Draw the background
|
||||
if (myConfig.bgColor != null)
|
||||
{
|
||||
g2d.setColor(myConfig.bgColor);
|
||||
g2d.fill(aRect);
|
||||
}
|
||||
|
||||
// Draw the border
|
||||
if (myConfig.borderColor != null && myConfig.borderWidth > 0)
|
||||
{
|
||||
g2d.setColor(myConfig.borderColor);
|
||||
g2d.setStroke(new BasicStroke(myConfig.borderWidth));
|
||||
g2d.draw(aRect);
|
||||
}
|
||||
|
||||
// Draw the displayMsg
|
||||
sX = winW / 2.0 - msgW / 2.0;
|
||||
sY = winH / 2.0 - msgH / 2.0;
|
||||
g2d.setFont(myConfig.font);
|
||||
g2d.setColor(myConfig.fgColor);
|
||||
g2d.drawString(displayMsg, (int)sX, (int)(sY + offSetY));
|
||||
}
|
||||
|
||||
/**
|
||||
* setConfig - Sets in the new banner attributes
|
||||
*/
|
||||
public void setConfig(BannerConfig aConfig)
|
||||
{
|
||||
// Insanity check
|
||||
if (aConfig == null)
|
||||
return;
|
||||
myConfig = aConfig;
|
||||
|
||||
// Build the actual displayMsg
|
||||
if (myConfig.numRepeats > 1)
|
||||
{
|
||||
displayMsg = "";
|
||||
for (int c1 = 0; c1 < myConfig.numRepeats; c1++)
|
||||
displayMsg += myConfig.bannerMsg;
|
||||
}
|
||||
else
|
||||
{
|
||||
displayMsg = myConfig.bannerMsg;
|
||||
}
|
||||
|
||||
// Time for a repaint
|
||||
repaint();
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method that converts a string to a BannerConfig. Eventually this method class should be
|
||||
* moved to a utility class of sorts.
|
||||
*/
|
||||
public static BannerConfig readBannerConfig(String strLine)
|
||||
{
|
||||
BannerConfig aConfig;
|
||||
Collection<String> instrSet, parmSet;
|
||||
Tokenizer instrTokenizer, parmTokenizer;
|
||||
String parms[];
|
||||
|
||||
// Insanity check
|
||||
if (strLine == null)
|
||||
return null;
|
||||
|
||||
// Build our tokenizers
|
||||
instrTokenizer = new MatchTokenizer("[^/]+");
|
||||
parmTokenizer = new MatchTokenizer("[^\\,]+");
|
||||
|
||||
// Get the set of embedded instructions
|
||||
instrSet = instrTokenizer.getTokens(strLine);
|
||||
|
||||
// Process the instruction
|
||||
aConfig = new BannerConfig();
|
||||
for (String aInstr : instrSet)
|
||||
{
|
||||
parmSet = parmTokenizer.getTokens(aInstr);
|
||||
parms = parmSet.toArray(new String[] {""});
|
||||
|
||||
if (parms.length == 0)
|
||||
{
|
||||
; // Nothing to process
|
||||
}
|
||||
else if (parms[0].equalsIgnoreCase("refName") == true && parms.length == 2)
|
||||
{
|
||||
aConfig.refName = parms[1];
|
||||
}
|
||||
else if (parms[0].equalsIgnoreCase("label") == true && parms.length == 2)
|
||||
{
|
||||
aConfig.bannerMsg = parms[1];
|
||||
}
|
||||
else if (parms[0].equalsIgnoreCase("font") == true && parms.length >= 2)
|
||||
{
|
||||
String face;
|
||||
int style, size;
|
||||
boolean bold, italic;
|
||||
|
||||
face = parms[1];
|
||||
|
||||
size = 12;
|
||||
if (parms.length > 2)
|
||||
size = GuiUtil.readInt(parms[2], 12);
|
||||
|
||||
bold = false;
|
||||
if (parms.length > 3)
|
||||
bold = GuiUtil.readBoolean(parms[3], false);
|
||||
|
||||
italic = false;
|
||||
if (parms.length > 4)
|
||||
italic = GuiUtil.readBoolean(parms[4], false);
|
||||
|
||||
style = 0;
|
||||
if (bold == false && italic == false)
|
||||
style = Font.PLAIN;
|
||||
if (bold == true)
|
||||
style = Font.BOLD;
|
||||
if (italic == true)
|
||||
style |= Font.ITALIC;
|
||||
|
||||
aConfig.font = new Font(face, style, size);
|
||||
}
|
||||
else if (parms[0].equalsIgnoreCase("fgColor") == true && parms.length == 4)
|
||||
{
|
||||
int r, g, b;
|
||||
|
||||
r = GuiUtil.readRangeInt(parms[1], 0, 255, 255);
|
||||
g = GuiUtil.readRangeInt(parms[2], 0, 255, 255);
|
||||
b = GuiUtil.readRangeInt(parms[3], 0, 255, 255);
|
||||
aConfig.fgColor = new Color(r, g, b);
|
||||
}
|
||||
else if (parms[0].equalsIgnoreCase("bgColor") == true && parms.length >= 4)
|
||||
{
|
||||
int r, g, b, a;
|
||||
|
||||
r = GuiUtil.readRangeInt(parms[1], 0, 255, 255);
|
||||
g = GuiUtil.readRangeInt(parms[2], 0, 255, 255);
|
||||
b = GuiUtil.readRangeInt(parms[3], 0, 255, 255);
|
||||
|
||||
a = 255;
|
||||
if (parms.length > 4)
|
||||
a = GuiUtil.readRangeInt(parms[4], 0, 255, 255);
|
||||
|
||||
aConfig.bgColor = new Color(r, g, b, a);
|
||||
}
|
||||
else if (parms[0].equalsIgnoreCase("border") == true && parms.length >= 4)
|
||||
{
|
||||
int r, g, b;
|
||||
|
||||
r = GuiUtil.readRangeInt(parms[1], 0, 255, 255);
|
||||
g = GuiUtil.readRangeInt(parms[2], 0, 255, 255);
|
||||
b = GuiUtil.readRangeInt(parms[3], 0, 255, 255);
|
||||
aConfig.borderColor = new Color(r, g, b);
|
||||
|
||||
if (parms.length > 4)
|
||||
aConfig.borderWidth = GuiUtil.readRangeInt(parms[4], 0, 10, 0);
|
||||
|
||||
if (parms.length > 5)
|
||||
aConfig.borderPad = GuiUtil.readRangeInt(parms[5], -20, 20, 0);
|
||||
}
|
||||
else if (parms[0].equalsIgnoreCase("repeatMsg") == true && parms.length == 2)
|
||||
{
|
||||
aConfig.numRepeats = GuiUtil.readRangeInt(parms[1], -1, 100, 0);
|
||||
}
|
||||
}
|
||||
|
||||
return aConfig;
|
||||
}
|
||||
|
||||
}
|
||||
36
src/glum/gui/component/banner/BannerConfig.java
Normal file
36
src/glum/gui/component/banner/BannerConfig.java
Normal file
@@ -0,0 +1,36 @@
|
||||
package glum.gui.component.banner;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
public class BannerConfig
|
||||
{
|
||||
// State vars
|
||||
public String refName;
|
||||
|
||||
public Color bgColor, fgColor;
|
||||
public Color borderColor;
|
||||
public int borderWidth, borderPad;
|
||||
|
||||
public Font font;
|
||||
public int numRepeats;
|
||||
public String bannerMsg;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public BannerConfig()
|
||||
{
|
||||
refName = "DEFAULT";
|
||||
|
||||
bgColor = Color.BLACK;
|
||||
fgColor = Color.WHITE;
|
||||
borderColor = null;
|
||||
borderWidth = 0;
|
||||
borderPad = 0;
|
||||
|
||||
font = new Font("Serif", Font.PLAIN, 12);
|
||||
numRepeats = 1;
|
||||
bannerMsg = "Banner";
|
||||
}
|
||||
|
||||
}
|
||||
60
src/glum/gui/component/model/GComboBoxModel.java
Normal file
60
src/glum/gui/component/model/GComboBoxModel.java
Normal file
@@ -0,0 +1,60 @@
|
||||
package glum.gui.component.model;
|
||||
|
||||
import java.util.Collection;
|
||||
import javax.swing.ComboBoxModel;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
public class GComboBoxModel<G1> extends GListModel<G1> implements ComboBoxModel
|
||||
{
|
||||
protected G1 chosenItem;
|
||||
|
||||
public GComboBoxModel(G1... aItemArr)
|
||||
{
|
||||
this(Lists.newArrayList(aItemArr));
|
||||
}
|
||||
|
||||
public GComboBoxModel(Collection<G1> aItemList)
|
||||
{
|
||||
super(aItemList);
|
||||
|
||||
chosenItem = null;
|
||||
if (itemList.size() > 0)
|
||||
chosenItem = itemList.get(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addItem(G1 aItem)
|
||||
{
|
||||
if (chosenItem == null)
|
||||
chosenItem = aItem;
|
||||
|
||||
super.addItem(aItem);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeItem(G1 aItem)
|
||||
{
|
||||
super.removeItem(aItem);
|
||||
|
||||
chosenItem = null;
|
||||
if (itemList.size() > 0)
|
||||
chosenItem = itemList.get(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Note aItem must be of the Generified type
|
||||
*/
|
||||
@Override @SuppressWarnings("unchecked")
|
||||
public void setSelectedItem(Object aItem)
|
||||
{
|
||||
chosenItem = (G1)aItem;
|
||||
}
|
||||
|
||||
@Override
|
||||
public G1 getSelectedItem()
|
||||
{
|
||||
return chosenItem;
|
||||
}
|
||||
|
||||
}
|
||||
98
src/glum/gui/component/model/GListModel.java
Normal file
98
src/glum/gui/component/model/GListModel.java
Normal file
@@ -0,0 +1,98 @@
|
||||
package glum.gui.component.model;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.AbstractListModel;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
/**
|
||||
* Generified mutable ListModel
|
||||
*/
|
||||
public class GListModel<G1> extends AbstractListModel
|
||||
{
|
||||
protected List<G1> itemList;
|
||||
|
||||
public GListModel(Collection<G1> aItemList)
|
||||
{
|
||||
itemList = Lists.newArrayList(aItemList);
|
||||
}
|
||||
|
||||
public GListModel(G1... aItemArr)
|
||||
{
|
||||
itemList = Lists.newArrayList(aItemArr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds aItem to this model
|
||||
*/
|
||||
public void addItem(G1 aItem)
|
||||
{
|
||||
int index;
|
||||
|
||||
itemList.add(aItem);
|
||||
|
||||
index = itemList.size() - 1;
|
||||
fireIntervalAdded(this, index, index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes aItem from this model
|
||||
*/
|
||||
public void removeItem(G1 aItem)
|
||||
{
|
||||
int index;
|
||||
|
||||
index = itemList.indexOf(aItem);
|
||||
itemList.remove(aItem);
|
||||
|
||||
fireIntervalRemoved(this, index, index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all the items from this model
|
||||
*/
|
||||
public void removeAllItems()
|
||||
{
|
||||
int lastIndex;
|
||||
|
||||
// Bail if the list is empty
|
||||
if (itemList.isEmpty() == true)
|
||||
return;
|
||||
|
||||
lastIndex = itemList.size() - 1;
|
||||
itemList.clear();
|
||||
|
||||
fireIntervalRemoved(this, 0, lastIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of all the items
|
||||
*/
|
||||
public ArrayList<G1> getAllItems()
|
||||
{
|
||||
return Lists.newArrayList(itemList);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index of the item located in this model.
|
||||
*/
|
||||
public int indexOf(G1 aItem)
|
||||
{
|
||||
return itemList.indexOf(aItem);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize()
|
||||
{
|
||||
return itemList.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public G1 getElementAt(int index)
|
||||
{
|
||||
return itemList.get(index);
|
||||
}
|
||||
}
|
||||
142
src/glum/gui/dialog/MemoryUtilDialog.java
Normal file
142
src/glum/gui/dialog/MemoryUtilDialog.java
Normal file
@@ -0,0 +1,142 @@
|
||||
package glum.gui.dialog;
|
||||
|
||||
import java.awt.Font;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.text.DecimalFormat;
|
||||
import javax.swing.*;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
import glum.gui.FocusUtil;
|
||||
import glum.gui.GuiUtil;
|
||||
import glum.gui.action.ClickAction;
|
||||
import glum.gui.component.GLabel;
|
||||
import glum.unit.ConstUnitProvider;
|
||||
import glum.unit.NumberUnit;
|
||||
import glum.unit.UnitProvider;
|
||||
|
||||
public class MemoryUtilDialog extends JDialog implements ActionListener
|
||||
{
|
||||
// Gui components
|
||||
private GLabel totalMemL, freeMemL, usedMemL;
|
||||
private UnitProvider byteUP;
|
||||
private JButton closeB, gcRunB, updateB;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public MemoryUtilDialog(JFrame parentFrame)
|
||||
{
|
||||
super(parentFrame);
|
||||
|
||||
setTitle("JVM Memory Usage");
|
||||
setDefaultCloseOperation(HIDE_ON_CLOSE);
|
||||
setModal(false);
|
||||
|
||||
DecimalFormat numFormat;
|
||||
numFormat = new DecimalFormat();
|
||||
numFormat.setGroupingUsed(true);
|
||||
numFormat.setGroupingSize(3);
|
||||
numFormat.setMaximumFractionDigits(0);
|
||||
byteUP = new ConstUnitProvider(new NumberUnit("MB", "MB", 1.0 / (1024 * 1024), numFormat));
|
||||
|
||||
// Place the dialog in the center
|
||||
buildGuiArea();
|
||||
setLocationRelativeTo(parentFrame);
|
||||
|
||||
// Set up keyboard short cuts
|
||||
FocusUtil.addWindowKeyBinding(getRootPane(), "ESCAPE", new ClickAction(closeB));
|
||||
FocusUtil.addWindowKeyBinding(getRootPane(), "ENTER", new ClickAction(updateB));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e)
|
||||
{
|
||||
Object source;
|
||||
|
||||
source = e.getSource();
|
||||
if (source == gcRunB)
|
||||
{
|
||||
System.gc();
|
||||
updateGui();
|
||||
}
|
||||
else if (source == updateB)
|
||||
{
|
||||
updateGui();
|
||||
}
|
||||
else if (source == closeB)
|
||||
{
|
||||
setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVisible(boolean isVisible)
|
||||
{
|
||||
updateGui();
|
||||
super.setVisible(isVisible);
|
||||
}
|
||||
|
||||
/**
|
||||
* Forms the actual dialog GUI
|
||||
*/
|
||||
private void buildGuiArea()
|
||||
{
|
||||
JPanel aPanel;
|
||||
JLabel tmpL;
|
||||
Font tmpFont;
|
||||
|
||||
// Form the panel
|
||||
aPanel = new JPanel(new MigLayout("", "[right][left,grow]", "[][][]10[]10"));
|
||||
tmpFont = new JTextField().getFont();
|
||||
|
||||
// Info area
|
||||
tmpL = new JLabel("Total Memory:");
|
||||
totalMemL = new GLabel(byteUP, tmpFont, true);
|
||||
aPanel.add(tmpL, "");
|
||||
aPanel.add(totalMemL, "growx,wrap");
|
||||
|
||||
tmpL = new JLabel("Free Memory:");
|
||||
freeMemL = new GLabel(byteUP, tmpFont, true);
|
||||
aPanel.add(tmpL, "");
|
||||
aPanel.add(freeMemL, "growx,wrap");
|
||||
|
||||
tmpL = new JLabel("Used Memory:");
|
||||
usedMemL = new GLabel(byteUP, tmpFont, true);
|
||||
aPanel.add(tmpL, "");
|
||||
aPanel.add(usedMemL, "growx,wrap");
|
||||
|
||||
// Control area
|
||||
updateB = GuiUtil.createJButton("Update", this);
|
||||
gcRunB = GuiUtil.createJButton("Run GC", this);
|
||||
closeB = GuiUtil.createJButton("Close", this);
|
||||
aPanel.add(updateB, "span 2,split 3");
|
||||
aPanel.add(gcRunB, "");
|
||||
aPanel.add(closeB, "");
|
||||
|
||||
// Add the main panel into the dialog
|
||||
getContentPane().add(aPanel);
|
||||
pack();
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to update the Gui
|
||||
*/
|
||||
private void updateGui()
|
||||
{
|
||||
Runtime aRuntime;
|
||||
long freeMem, usedMem, totalMem;
|
||||
|
||||
aRuntime = Runtime.getRuntime();
|
||||
|
||||
// Update the memory usage
|
||||
freeMem = aRuntime.freeMemory();
|
||||
totalMem = aRuntime.totalMemory();
|
||||
usedMem = totalMem - freeMem;
|
||||
|
||||
freeMemL.setValue(freeMem);
|
||||
totalMemL.setValue(totalMem);
|
||||
usedMemL.setValue(usedMem);
|
||||
}
|
||||
|
||||
}
|
||||
52
src/glum/gui/dnd/PlainTransferHandler.java
Normal file
52
src/glum/gui/dnd/PlainTransferHandler.java
Normal file
@@ -0,0 +1,52 @@
|
||||
package glum.gui.dnd;
|
||||
|
||||
import java.awt.datatransfer.Transferable;
|
||||
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.TransferHandler;
|
||||
|
||||
/**
|
||||
* Generic TransferHandler that supports transferring an arbitrary Transferable. Note that before the DnD transfer
|
||||
* mechanism is triggered via the method exportAsDrag(), the developer must set in the Transferable via the method
|
||||
* setWorkTransferable().
|
||||
*/
|
||||
public class PlainTransferHandler extends TransferHandler
|
||||
{
|
||||
// State vars
|
||||
protected Transferable workTransferable;
|
||||
|
||||
public PlainTransferHandler()
|
||||
{
|
||||
super();
|
||||
|
||||
workTransferable = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to set in the current "active" Trasferable for which this TrasferHandler will process.
|
||||
*/
|
||||
public void setWorkTransferable(Transferable aTransferable)
|
||||
{
|
||||
workTransferable = aTransferable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSourceActions(JComponent aComp)
|
||||
{
|
||||
return COPY_OR_MOVE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Transferable createTransferable(JComponent aComp)
|
||||
{
|
||||
// Just return the active Transferable
|
||||
return workTransferable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exportDone(JComponent c, Transferable t, int action)
|
||||
{
|
||||
workTransferable = null;
|
||||
}
|
||||
|
||||
}
|
||||
50
src/glum/gui/dock/BaseDockable.java
Normal file
50
src/glum/gui/dock/BaseDockable.java
Normal file
@@ -0,0 +1,50 @@
|
||||
package glum.gui.dock;
|
||||
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.JComponent;
|
||||
|
||||
import bibliothek.gui.DockStation;
|
||||
import bibliothek.gui.dock.DefaultDockable;
|
||||
|
||||
public class BaseDockable extends DefaultDockable
|
||||
{
|
||||
// Tells whether this Dockable can be dragged and dropped to another station
|
||||
private DockStation homeStation;
|
||||
private boolean isTransferable;
|
||||
|
||||
public BaseDockable()
|
||||
{
|
||||
super();
|
||||
|
||||
isTransferable = true;
|
||||
}
|
||||
|
||||
public BaseDockable(JComponent aComp, String aTitle, Icon aIcon)
|
||||
{
|
||||
super(aComp, aTitle, aIcon);
|
||||
|
||||
isTransferable = true;
|
||||
}
|
||||
|
||||
public boolean isTransferable(DockStation aStation)
|
||||
{
|
||||
if (isTransferable == true)
|
||||
return true;
|
||||
|
||||
// We can only be transfered to our homeStation when we are not transferable
|
||||
return aStation == homeStation;
|
||||
}
|
||||
|
||||
public void setTransferable(boolean aBool)
|
||||
{
|
||||
homeStation = null;
|
||||
isTransferable = aBool;
|
||||
|
||||
|
||||
// Record our parent when we become non transferable
|
||||
if (isTransferable == false)
|
||||
homeStation = getDockParent();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
34
src/glum/gui/dock/CloseableDockable.java
Normal file
34
src/glum/gui/dock/CloseableDockable.java
Normal file
@@ -0,0 +1,34 @@
|
||||
package glum.gui.dock;
|
||||
|
||||
import glum.gui.dock.action.Closeable;
|
||||
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.JComponent;
|
||||
|
||||
import bibliothek.gui.DockFrontend;
|
||||
|
||||
/**
|
||||
* Dockable class to wrap aComp into a DefaultDockable using the specified title and icon. This Dockable will be
|
||||
* automatically installed into aFrontend and support proper closing via the {@link Closeable} interface.
|
||||
*/
|
||||
public class CloseableDockable extends BaseDockable implements Closeable
|
||||
{
|
||||
protected DockFrontend refFrontend;
|
||||
|
||||
public CloseableDockable(DockFrontend aFrontend, String idName, JComponent aComp, String aTitle, Icon aIcon)
|
||||
{
|
||||
super(aComp, aTitle, aIcon);
|
||||
setTitleIcon(aIcon);
|
||||
|
||||
// Register ourselves with the refFrontend
|
||||
refFrontend = aFrontend;
|
||||
refFrontend.addDockable(idName, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close()
|
||||
{
|
||||
refFrontend.hide(this);
|
||||
}
|
||||
|
||||
}
|
||||
61
src/glum/gui/dock/CustomPlaceholderStrategy.java
Normal file
61
src/glum/gui/dock/CustomPlaceholderStrategy.java
Normal file
@@ -0,0 +1,61 @@
|
||||
package glum.gui.dock;
|
||||
|
||||
import bibliothek.gui.DockStation;
|
||||
import bibliothek.gui.Dockable;
|
||||
import bibliothek.gui.dock.station.support.PlaceholderStrategy;
|
||||
import bibliothek.gui.dock.station.support.PlaceholderStrategyListener;
|
||||
import bibliothek.util.Path;
|
||||
|
||||
/*
|
||||
* This is our very simple PlaceholderStrategy. It only recognizes our custom
|
||||
* PrimDockable and returns the associated place holder.
|
||||
*
|
||||
* TODO: This class is incomplete. It might be deleted in the future.
|
||||
*/
|
||||
public class CustomPlaceholderStrategy implements PlaceholderStrategy
|
||||
{
|
||||
@Override
|
||||
public void addListener(PlaceholderStrategyListener listener)
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path getPlaceholderFor(Dockable aDockable)
|
||||
{
|
||||
// We handle only PrimDockables
|
||||
if (aDockable instanceof PrimDock == false)
|
||||
return null;
|
||||
|
||||
//System.out.println("Attempting to add placeholder for dockable: " + aDockable.getTitleText());
|
||||
// return new Path("Prim:" + ((PrimDockable)aDockable).getUniqueId());
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void install(DockStation station)
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidPlaceholder(Path placeholder)
|
||||
{
|
||||
System.out.println("isValidPlaceholder()-> Path:" + placeholder.toString());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeListener(PlaceholderStrategyListener listener)
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
|
||||
@Override
|
||||
public void uninstall(DockStation station)
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
|
||||
}
|
||||
213
src/glum/gui/dock/DockUtil.java
Normal file
213
src/glum/gui/dock/DockUtil.java
Normal file
@@ -0,0 +1,213 @@
|
||||
package glum.gui.dock;
|
||||
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.swing.Icon;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
import bibliothek.gui.DockController;
|
||||
import bibliothek.gui.DockFrontend;
|
||||
import bibliothek.gui.DockStation;
|
||||
import bibliothek.gui.Dockable;
|
||||
import bibliothek.gui.dock.ScreenDockStation;
|
||||
import bibliothek.gui.dock.SplitDockStation;
|
||||
import bibliothek.gui.dock.action.DockAction;
|
||||
import bibliothek.gui.dock.action.actions.SimpleButtonAction;
|
||||
import bibliothek.gui.dock.station.screen.ScreenFullscreenAction;
|
||||
import bibliothek.gui.dock.station.split.SplitFullScreenAction;
|
||||
|
||||
public class DockUtil
|
||||
{
|
||||
/**
|
||||
* Utility method to construct a SimpleButtonAction.
|
||||
*/
|
||||
public static SimpleButtonAction createAction(String aText, Icon aIcon, ActionListener aListener)
|
||||
{
|
||||
SimpleButtonAction aAction;
|
||||
|
||||
aAction = new SimpleButtonAction();
|
||||
aAction.setText(aText);
|
||||
aAction.setIcon(aIcon);
|
||||
aAction.addActionListener(aListener);
|
||||
|
||||
return aAction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to return the appropriate DockAction associated with aStation which will cause a "full screen"
|
||||
* action to be executed. Currently only object of type {@link SplitDockStation} and {@link ScreenDockStation} are
|
||||
* supported.
|
||||
*/
|
||||
public static DockAction createFullScreenAction(DockStation aStation, DockController aController)
|
||||
{
|
||||
DockAction fullScreenAction;
|
||||
|
||||
if (aStation instanceof SplitDockStation)
|
||||
{
|
||||
fullScreenAction = new SplitFullScreenAction((SplitDockStation)aStation);
|
||||
((SplitFullScreenAction)fullScreenAction).setController(aController);
|
||||
}
|
||||
else if (aStation instanceof ScreenDockStation)
|
||||
{
|
||||
fullScreenAction = new ScreenFullscreenAction((ScreenDockStation)aStation);
|
||||
((ScreenFullscreenAction)fullScreenAction).setController(aController);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new RuntimeException("Unsupported Dockable type: " + aStation);
|
||||
}
|
||||
|
||||
return fullScreenAction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to locate the first Dockable (contained within aStation) which is of type aClass
|
||||
*/
|
||||
public static <G1 extends Dockable> G1 findDockable(DockStation aStation, Class<G1> aClass)
|
||||
{
|
||||
Dockable evalDockable;
|
||||
|
||||
for (int c1 = 0; c1 < aStation.getDockableCount(); c1++)
|
||||
{
|
||||
evalDockable = aStation.getDockable(c1);
|
||||
if (evalDockable instanceof DockStation)
|
||||
evalDockable = findDockable((DockStation)evalDockable, aClass);
|
||||
|
||||
if (evalDockable.getClass() == aClass)
|
||||
return aClass.cast(evalDockable);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to locate the list of Dockables (contained within aFrontend) which is of one of the types in aClassArr. All
|
||||
* child DockStations will be searched.
|
||||
*/
|
||||
public static List<Dockable> findDockableList(DockFrontend aFrontend, Class<?>... aClassArr)
|
||||
{
|
||||
Set<Class<?>> classSet;
|
||||
List<Dockable> itemList;
|
||||
|
||||
// Transform the match class array to a set
|
||||
classSet = Sets.newHashSet();
|
||||
for (Class<?> aClass : aClassArr)
|
||||
classSet.add(aClass);
|
||||
|
||||
itemList = Lists.newLinkedList();
|
||||
for (DockStation aStation : aFrontend.getRoots())
|
||||
findDockableList(aStation, classSet, itemList);
|
||||
|
||||
return itemList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to locate the list of Dockables (contained within aFrontend) which is of type of aClass. All child
|
||||
* DockStations will be searched.
|
||||
*/
|
||||
public static <G1 extends Dockable> List<G1> findDockableList(DockFrontend aFrontend, Class<G1> aClass)
|
||||
{
|
||||
Set<Class<?>> classSet;
|
||||
List<G1> itemList;
|
||||
|
||||
// Transform the match class array to a set
|
||||
classSet = Sets.newHashSet();
|
||||
classSet.add(aClass);
|
||||
|
||||
itemList = Lists.newLinkedList();
|
||||
for (DockStation aStation : aFrontend.getRoots())
|
||||
findDockableList(aStation, classSet, itemList);
|
||||
|
||||
return itemList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to locate the list of Dockables (contained within aStation) which is of one of the types in aClassArr. All
|
||||
* child DockStations will be searched.
|
||||
*/
|
||||
public static List<Dockable> findDockableList(DockStation aStation, Class<?>... aClassArr)
|
||||
{
|
||||
Set<Class<?>> classSet;
|
||||
List<Dockable> itemList;
|
||||
|
||||
// Transform the match class array to a set
|
||||
classSet = Sets.newHashSet();
|
||||
for (Class<?> aClass : aClassArr)
|
||||
classSet.add(aClass);
|
||||
|
||||
itemList = Lists.newLinkedList();
|
||||
findDockableList(aStation, classSet, itemList);
|
||||
|
||||
return itemList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to locate the list of Dockables (contained within aStation) which is of type of aClass. All child
|
||||
* DockStations will be searched.
|
||||
*/
|
||||
public static <G1 extends Dockable> List<G1> findDockableList(DockStation aStation, Class<G1> aClass)
|
||||
{
|
||||
Set<Class<?>> classSet;
|
||||
List<G1> itemList;
|
||||
|
||||
// Transform the match class array to a set
|
||||
classSet = Sets.newHashSet();
|
||||
classSet.add(aClass);
|
||||
|
||||
itemList = Lists.newLinkedList();
|
||||
findDockableList(aStation, classSet, itemList);
|
||||
|
||||
return itemList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to remove all PlotGroupStations and ChartDockables
|
||||
*/
|
||||
public static <G1 extends Dockable> void removeAllDockablesOfType(DockFrontend aFrontend, Class<?>... dockTypeArr)
|
||||
{
|
||||
List<Dockable> dockList;
|
||||
DockStation dockStation;
|
||||
|
||||
// Gather all of the Dockables of interest
|
||||
dockList = DockUtil.findDockableList(aFrontend, dockTypeArr);
|
||||
|
||||
// Remove all of the Dockables
|
||||
for (Dockable aDock : dockList)
|
||||
{
|
||||
dockStation = aDock.getDockParent();
|
||||
if (dockStation != null)
|
||||
dockStation.drag(aDock);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursive helper method to locate the list of Dockables (contained within aStation) which is of type aClass. The
|
||||
* results will be stored in aItemList
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private static <G1 extends Dockable> void findDockableList(DockStation aStation, Set<Class<?>> aClassSet, List<G1> aItemList)
|
||||
{
|
||||
Dockable evalDockable;
|
||||
|
||||
for (int c1 = 0; c1 < aStation.getDockableCount(); c1++)
|
||||
{
|
||||
evalDockable = aStation.getDockable(c1);
|
||||
for (Class<?> aClass : aClassSet)
|
||||
{
|
||||
if (aClass.isAssignableFrom(evalDockable.getClass()) == true)
|
||||
{
|
||||
aItemList.add((G1)evalDockable);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (evalDockable instanceof DockStation)
|
||||
findDockableList((DockStation)evalDockable, aClassSet, aItemList);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
86
src/glum/gui/dock/FrontendAddConfigPanel.java
Normal file
86
src/glum/gui/dock/FrontendAddConfigPanel.java
Normal file
@@ -0,0 +1,86 @@
|
||||
package glum.gui.dock;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
|
||||
import bibliothek.gui.DockFrontend;
|
||||
|
||||
import glum.gui.panel.generic.TextInputPanel;
|
||||
|
||||
public class FrontendAddConfigPanel extends TextInputPanel
|
||||
{
|
||||
// Constants
|
||||
public static final String DEFAULT_NAME = "Default";
|
||||
|
||||
// State vars
|
||||
protected DockFrontend refFrontend;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public FrontendAddConfigPanel(Component aParent, DockFrontend aFrontend)
|
||||
{
|
||||
super(aParent);
|
||||
|
||||
refFrontend = aFrontend;
|
||||
|
||||
// Set in a more specific title and input label
|
||||
titleL.setText("Save configuration as:");
|
||||
inputL.setText("Name:");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e)
|
||||
{
|
||||
Object source;
|
||||
String configName;
|
||||
|
||||
// Save of the configuration
|
||||
source = e.getSource();
|
||||
if (source == acceptB)
|
||||
{
|
||||
configName = getInput();
|
||||
refFrontend.save(configName);
|
||||
}
|
||||
|
||||
// Call parent behavior
|
||||
super.actionPerformed(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateGui()
|
||||
{
|
||||
String inputStr, infoMsg;
|
||||
boolean isEnabled;
|
||||
|
||||
// Assume the GUI is invalid
|
||||
isEnabled = false;
|
||||
|
||||
// Retrieve the name
|
||||
inputStr = inputTF.getText();
|
||||
|
||||
// Determine the validity of specified name
|
||||
if (inputStr.equals("") == true)
|
||||
{
|
||||
infoMsg = "Please enter a valid configuration name.";
|
||||
}
|
||||
else if (inputStr.startsWith(".") == true)
|
||||
{
|
||||
infoMsg = "Invalid name. Name can not start with the char '.'";
|
||||
}
|
||||
else if (refFrontend.getSetting(inputStr) != null)
|
||||
{
|
||||
infoMsg = "Name in use. Configuration will be overwritten.";
|
||||
isEnabled = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
infoMsg = "";
|
||||
isEnabled = true;
|
||||
}
|
||||
|
||||
infoL.setText(infoMsg);
|
||||
acceptB.setEnabled(isEnabled);
|
||||
}
|
||||
|
||||
}
|
||||
252
src/glum/gui/dock/FrontendManageConfigPanel.java
Normal file
252
src/glum/gui/dock/FrontendManageConfigPanel.java
Normal file
@@ -0,0 +1,252 @@
|
||||
package glum.gui.dock;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.Collection;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.border.BevelBorder;
|
||||
import javax.swing.event.ListSelectionEvent;
|
||||
import javax.swing.event.ListSelectionListener;
|
||||
|
||||
//import echo.gui.LookUp;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import glum.database.QueryItem;
|
||||
import glum.gui.FocusUtil;
|
||||
import glum.gui.GuiUtil;
|
||||
import glum.gui.action.ClickAction;
|
||||
import glum.gui.panel.GlassPanel;
|
||||
import glum.gui.panel.itemList.ItemListPanel;
|
||||
import glum.gui.panel.itemList.StaticItemProcessor;
|
||||
import glum.gui.panel.itemList.query.QueryComposer;
|
||||
import glum.gui.panel.itemList.query.QueryItemHandler;
|
||||
|
||||
import bibliothek.gui.DockFrontend;
|
||||
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
public class FrontendManageConfigPanel extends GlassPanel implements ActionListener, ListSelectionListener
|
||||
{
|
||||
// GUI vars
|
||||
protected ItemListPanel<ConfigItem> listPanel;
|
||||
protected JButton deleteB, closeB;
|
||||
|
||||
// State vars
|
||||
protected DockFrontend refFrontend;
|
||||
protected StaticItemProcessor<ConfigItem> myItemProcessor;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param aFrontend
|
||||
*/
|
||||
public FrontendManageConfigPanel(Component aParent, DockFrontend aFrontend)
|
||||
{
|
||||
super(aParent);
|
||||
|
||||
// State vars
|
||||
refFrontend = aFrontend;
|
||||
|
||||
// Build the actual GUI
|
||||
buildGuiArea();
|
||||
setPreferredSize(new Dimension(250, 300));//TODO:getPreferredSize().height));
|
||||
|
||||
// Set up keyboard short cuts
|
||||
FocusUtil.addAncestorKeyBinding(this, "ESCAPE", new ClickAction(closeB));
|
||||
FocusUtil.addAncestorKeyBinding(this, "ENTER", new ClickAction(closeB));
|
||||
FocusUtil.addFocusKeyBinding(listPanel.getTable(), "ENTER", new ClickAction(closeB));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVisible(boolean aBool)
|
||||
{
|
||||
resetGui();
|
||||
|
||||
super.setVisible(aBool);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e)
|
||||
{
|
||||
Object source;
|
||||
ConfigItem chosenItem;
|
||||
|
||||
chosenItem = listPanel.getSelectedItem();
|
||||
|
||||
source = e.getSource();
|
||||
if (source == deleteB)
|
||||
{
|
||||
refFrontend.delete(chosenItem.getName());
|
||||
resetGui();
|
||||
}
|
||||
else if (source == closeB)
|
||||
{
|
||||
setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void valueChanged(ListSelectionEvent aEvent)
|
||||
{
|
||||
if (aEvent.getValueIsAdjusting() == true)
|
||||
return;
|
||||
|
||||
updateGui();
|
||||
}
|
||||
|
||||
/**
|
||||
* buildGuiArea - Forms the actual dialog GUI
|
||||
*/
|
||||
private void buildGuiArea()
|
||||
{
|
||||
JLabel tmpL;
|
||||
QueryItemHandler<ConfigItem> aItemHandler;
|
||||
QueryComposer<LookUp> aComposer;
|
||||
|
||||
|
||||
setLayout(new MigLayout("", "[grow][][]", "[][grow][]"));
|
||||
|
||||
tmpL = new JLabel("Select configuration:", JLabel.CENTER);
|
||||
add(tmpL, "growx,span 4,wrap");
|
||||
|
||||
// Construct the actual table panel
|
||||
aComposer = new QueryComposer<LookUp>();
|
||||
aComposer.addAttribute(LookUp.Name, String.class, "Configuration", null);
|
||||
|
||||
myItemProcessor = new StaticItemProcessor<ConfigItem>();
|
||||
aItemHandler = new QueryItemHandler<ConfigItem>(aComposer);
|
||||
listPanel = new ItemListPanel<ConfigItem>(aItemHandler, myItemProcessor, false, true);
|
||||
listPanel.addListSelectionListener(this);
|
||||
add(listPanel, "growx,growy,span 4,wrap");
|
||||
|
||||
// Control area
|
||||
deleteB = GuiUtil.createJButton("Delete", this);
|
||||
closeB = GuiUtil.createJButton("Close", this);
|
||||
|
||||
add(deleteB, "skip 1,span 1");
|
||||
add(closeB, "span 1");
|
||||
|
||||
setBorder(new BevelBorder(BevelBorder.RAISED));
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to update item list
|
||||
*/
|
||||
private void resetGui()
|
||||
{
|
||||
Collection<String> strList;
|
||||
Collection<ConfigItem> itemList;
|
||||
|
||||
itemList = Lists.newLinkedList();
|
||||
|
||||
strList = refFrontend.getSettings();
|
||||
for (String aStr : strList)
|
||||
{
|
||||
// Add only non reserved items
|
||||
if (aStr.charAt(0) != '.')
|
||||
itemList.add(new ConfigItem(aStr));
|
||||
}
|
||||
|
||||
myItemProcessor.setItems(itemList);
|
||||
|
||||
// TODO: Ugly code: Should be able to just call updateGui but can not
|
||||
SwingUtilities.invokeLater(new Runnable()
|
||||
{
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
updateGui();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to update the individual gui components
|
||||
*/
|
||||
private void updateGui()
|
||||
{
|
||||
ConfigItem chosenItem;
|
||||
boolean isEnabled;
|
||||
|
||||
chosenItem = listPanel.getSelectedItem();
|
||||
|
||||
if (chosenItem != null)
|
||||
refFrontend.load(chosenItem.getName());
|
||||
|
||||
isEnabled = chosenItem != null;
|
||||
deleteB.setEnabled(isEnabled);
|
||||
|
||||
// Ensure we have the focus.
|
||||
//listPanel.requestFocusInWindow();
|
||||
repaint();
|
||||
|
||||
// TODO: Ugly code: Not sure why need to request focus multiple times to ensure we regrab
|
||||
// the focus. This is particularly true when there are multiple DockStations located on different
|
||||
// windows
|
||||
SwingUtilities.invokeLater(new Runnable()
|
||||
{
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
listPanel.getTable().requestFocus();
|
||||
|
||||
SwingUtilities.invokeLater(new Runnable()
|
||||
{
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
listPanel.getTable().requestFocus();
|
||||
}
|
||||
});
|
||||
|
||||
// listPanel.getTable().getFocusCycleRootAncestor().setFocusCycleRoot(true);
|
||||
listPanel.getTable().requestFocusInWindow();
|
||||
repaint();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Internal class only used to wrap named (string) settings into
|
||||
* a QueryItem
|
||||
*/
|
||||
class ConfigItem implements QueryItem<LookUp>
|
||||
{
|
||||
private String refName;
|
||||
|
||||
public ConfigItem(String aName)
|
||||
{
|
||||
refName = aName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accessor method
|
||||
*/
|
||||
public String getName()
|
||||
{
|
||||
return refName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue(LookUp aLookUp)
|
||||
{
|
||||
return refName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(LookUp aLookUp, Object aObj)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
7
src/glum/gui/dock/LookUp.java
Normal file
7
src/glum/gui/dock/LookUp.java
Normal file
@@ -0,0 +1,7 @@
|
||||
package glum.gui.dock;
|
||||
|
||||
public enum LookUp
|
||||
{
|
||||
Name
|
||||
|
||||
}
|
||||
64
src/glum/gui/dock/PlainDockSituationIgnore.java
Normal file
64
src/glum/gui/dock/PlainDockSituationIgnore.java
Normal file
@@ -0,0 +1,64 @@
|
||||
package glum.gui.dock;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
import bibliothek.gui.DockStation;
|
||||
import bibliothek.gui.dock.DockElement;
|
||||
import bibliothek.gui.dock.layout.DockSituationIgnore;
|
||||
import bibliothek.gui.dock.perspective.PerspectiveElement;
|
||||
import bibliothek.gui.dock.perspective.PerspectiveStation;
|
||||
|
||||
public class PlainDockSituationIgnore implements DockSituationIgnore
|
||||
{
|
||||
private Set<Class<?>> ignoreClassSet;
|
||||
|
||||
public PlainDockSituationIgnore()
|
||||
{
|
||||
ignoreClassSet = Sets.newLinkedHashSet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to register a new type of Dockable/Station to ignore
|
||||
*/
|
||||
public void addIgnoreClass(Class<?> aClass)
|
||||
{
|
||||
ignoreClassSet.add(aClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean ignoreElement(PerspectiveElement aElement)
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean ignoreElement(DockElement aElement)
|
||||
{
|
||||
// Check to see if aElement is of one of the types in ignoreClassSet
|
||||
for (Class<?> aClass : ignoreClassSet)
|
||||
{
|
||||
if (aClass.isAssignableFrom(aElement.getClass()) == true)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean ignoreChildren(PerspectiveStation station)
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean ignoreChildren(DockStation station)
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
322
src/glum/gui/dock/PrimConfig.java
Normal file
322
src/glum/gui/dock/PrimConfig.java
Normal file
@@ -0,0 +1,322 @@
|
||||
package glum.gui.dock;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
import glum.io.IoUtil;
|
||||
|
||||
public class PrimConfig
|
||||
{
|
||||
// Constants
|
||||
public static final byte CODE_BOOL = 1;
|
||||
public static final byte CODE_INT = 10;
|
||||
public static final byte CODE_LONG = 11;
|
||||
public static final byte CODE_SHORT = 12;
|
||||
public static final byte CODE_FLOAT = 13;
|
||||
public static final byte CODE_DOUBLE = 14;
|
||||
public static final byte CODE_STRING = 20;
|
||||
|
||||
// State vars
|
||||
protected Map<String, Object> mySingletonMap;
|
||||
|
||||
/**
|
||||
* Container which holds a mapping of keys (String) to a bunch
|
||||
* of primitive objects.
|
||||
*/
|
||||
public PrimConfig()
|
||||
{
|
||||
mySingletonMap = Maps.newLinkedHashMap();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the boolean associated with aKey
|
||||
* If no such value is found then defaultVal is returned.
|
||||
*/
|
||||
public boolean getBoolean(String aKey, boolean defaultVal)
|
||||
{
|
||||
Object aValue;
|
||||
|
||||
// If no value associated with the key then return defaultVal
|
||||
aValue = mySingletonMap.get(aKey);
|
||||
if (aValue == null || aValue.getClass() != Boolean.class)
|
||||
return defaultVal;
|
||||
|
||||
return (Boolean)aValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the int associated with aKey
|
||||
* If no such value is found then defaultVal is returned.
|
||||
*/
|
||||
public int getInt(String aKey, int defaultVal)
|
||||
{
|
||||
Object aValue;
|
||||
|
||||
// If no value associated with the key then return defaultVal
|
||||
aValue = mySingletonMap.get(aKey);
|
||||
if (aValue == null || aValue.getClass() != Integer.class)
|
||||
return defaultVal;
|
||||
|
||||
return (Integer)aValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the long associated with aKey
|
||||
* If no such value is found then defaultVal is returned.
|
||||
*/
|
||||
public long getLong(String aKey, long defaultVal)
|
||||
{
|
||||
Object aValue;
|
||||
|
||||
// If no value associated with the key then return defaultVal
|
||||
aValue = mySingletonMap.get(aKey);
|
||||
if (aValue == null || aValue.getClass() != Long.class)
|
||||
return defaultVal;
|
||||
|
||||
return (Long)aValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the short associated with aKey
|
||||
* If no such value is found then defaultVal is returned.
|
||||
*/
|
||||
public short getShort(String aKey, short defaultVal)
|
||||
{
|
||||
Object aValue;
|
||||
|
||||
// If no value associated with the key then return defaultVal
|
||||
aValue = mySingletonMap.get(aKey);
|
||||
if (aValue == null || aValue.getClass() != Short.class)
|
||||
return defaultVal;
|
||||
|
||||
return (Short)aValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the float associated with aKey
|
||||
* If no such value is found then defaultVal is returned.
|
||||
*/
|
||||
public float getFloat(String aKey, float defaultVal)
|
||||
{
|
||||
Object aValue;
|
||||
|
||||
// If no value associated with the key then return defaultVal
|
||||
aValue = mySingletonMap.get(aKey);
|
||||
if (aValue == null || aValue.getClass() != Float.class)
|
||||
return defaultVal;
|
||||
|
||||
return (Float)aValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the double associated with aKey
|
||||
* If no such value is found then defaultVal is returned.
|
||||
*/
|
||||
public double getDouble(String aKey, double defaultVal)
|
||||
{
|
||||
Object aValue;
|
||||
|
||||
// If no value associated with the key then return defaultVal
|
||||
aValue = mySingletonMap.get(aKey);
|
||||
if (aValue == null || aValue.getClass() != Double.class)
|
||||
return defaultVal;
|
||||
|
||||
return (Double)aValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the String associated with aKey
|
||||
* If no such value is found then defaultVal is returned.
|
||||
*/
|
||||
public String getString(String aKey, String defaultVal)
|
||||
{
|
||||
Object aValue;
|
||||
|
||||
// If no value associated with the key then return defaultVal
|
||||
aValue = mySingletonMap.get(aKey);
|
||||
if (aValue == null || aValue.getClass() != String.class)
|
||||
return defaultVal;
|
||||
|
||||
return (String)aValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Associates aVal with aKey. Note this will overwrite any
|
||||
* previous association.
|
||||
*/
|
||||
public void setBoolean(String aKey, boolean aValue)
|
||||
{
|
||||
mySingletonMap.put(aKey, aValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Associates aVal with aKey. Note this will overwrite any
|
||||
* previous association.
|
||||
*/
|
||||
public void setInt(String aKey, int aValue)
|
||||
{
|
||||
mySingletonMap.put(aKey, aValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Associates aVal with aKey. Note this will overwrite any
|
||||
* previous association.
|
||||
*/
|
||||
public void setLong(String aKey, long aValue)
|
||||
{
|
||||
mySingletonMap.put(aKey, aValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Associates aVal with aKey. Note this will overwrite any
|
||||
* previous association.
|
||||
*/
|
||||
public void setShort(String aKey, short aValue)
|
||||
{
|
||||
mySingletonMap.put(aKey, aValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Associates aVal with aKey. Note this will overwrite any
|
||||
* previous association.
|
||||
*/
|
||||
public void setFloat(String aKey, float aValue)
|
||||
{
|
||||
mySingletonMap.put(aKey, aValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Associates aVal with aKey. Note this will overwrite any
|
||||
* previous association.
|
||||
*/
|
||||
public void setDouble(String aKey, double aValue)
|
||||
{
|
||||
mySingletonMap.put(aKey, aValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Associates aVal with aKey. Note this will overwrite any
|
||||
* previous association.
|
||||
*/
|
||||
public void setString(String aKey, String aValue)
|
||||
{
|
||||
mySingletonMap.put(aKey, aValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to read the configuration from a DataInputStream
|
||||
*/
|
||||
public void readBin(DataInputStream aStream) throws IOException
|
||||
{
|
||||
int numItems;
|
||||
String aKey;
|
||||
byte aType;
|
||||
|
||||
mySingletonMap.clear();
|
||||
|
||||
numItems = aStream.readInt();
|
||||
for (int c1 = 0; c1 < numItems; c1++)
|
||||
{
|
||||
aKey = IoUtil.readString(aStream);
|
||||
aType = aStream.readByte();
|
||||
|
||||
switch(aType)
|
||||
{
|
||||
case CODE_BOOL:
|
||||
mySingletonMap.put(aKey, aStream.readBoolean());
|
||||
break;
|
||||
|
||||
case CODE_INT:
|
||||
mySingletonMap.put(aKey, aStream.readInt());
|
||||
break;
|
||||
|
||||
case CODE_LONG:
|
||||
mySingletonMap.put(aKey, aStream.readLong());
|
||||
break;
|
||||
|
||||
case CODE_SHORT:
|
||||
mySingletonMap.put(aKey, aStream.readShort());
|
||||
break;
|
||||
|
||||
case CODE_FLOAT:
|
||||
mySingletonMap.put(aKey, aStream.readFloat());
|
||||
break;
|
||||
|
||||
case CODE_DOUBLE:
|
||||
mySingletonMap.put(aKey, aStream.readDouble());
|
||||
break;
|
||||
|
||||
case CODE_STRING:
|
||||
mySingletonMap.put(aKey, IoUtil.readString(aStream));
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new RuntimeException("Unreconnized type: " + aType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to write the configuration to a DataOutputStream
|
||||
*/
|
||||
public void writeBin(DataOutputStream aStream) throws IOException
|
||||
{
|
||||
Set<String> keySet;
|
||||
Object aVal;
|
||||
|
||||
keySet = mySingletonMap.keySet();
|
||||
|
||||
aStream.writeInt(keySet.size());
|
||||
for (String aKey : keySet)
|
||||
{
|
||||
IoUtil.writeString(aStream, aKey);
|
||||
|
||||
aVal = mySingletonMap.get(aKey);
|
||||
if (aVal instanceof Boolean)
|
||||
{
|
||||
aStream.writeByte(CODE_BOOL);
|
||||
aStream.writeBoolean((Boolean)aVal);
|
||||
}
|
||||
else if (aVal instanceof Integer)
|
||||
{
|
||||
aStream.writeByte(CODE_INT);
|
||||
aStream.writeInt((Integer)aVal);
|
||||
}
|
||||
else if (aVal instanceof Long)
|
||||
{
|
||||
aStream.writeByte(CODE_LONG);
|
||||
aStream.writeLong((Long)aVal);
|
||||
}
|
||||
else if (aVal instanceof Short)
|
||||
{
|
||||
aStream.writeByte(CODE_SHORT);
|
||||
aStream.writeLong((Short)aVal);
|
||||
}
|
||||
else if (aVal instanceof Float)
|
||||
{
|
||||
aStream.writeByte(CODE_FLOAT);
|
||||
aStream.writeFloat((Float)aVal);
|
||||
}
|
||||
else if (aVal instanceof Double)
|
||||
{
|
||||
aStream.writeByte(CODE_DOUBLE);
|
||||
aStream.writeDouble((Double)aVal);
|
||||
}
|
||||
else if (aVal instanceof String)
|
||||
{
|
||||
aStream.writeByte(CODE_STRING);
|
||||
IoUtil.writeString(aStream, (String)aVal);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new RuntimeException("Unsupported Object: " + aVal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
35
src/glum/gui/dock/PrimDock.java
Normal file
35
src/glum/gui/dock/PrimDock.java
Normal file
@@ -0,0 +1,35 @@
|
||||
package glum.gui.dock;
|
||||
|
||||
import bibliothek.gui.dock.DockElement;
|
||||
|
||||
/**
|
||||
* Base class for Dockables which would like to store their configuration via
|
||||
* the PrimConfig mechanism. Note if the child class will be loaded with the
|
||||
* PrimDockableFactory, then you should have a constructor with one of the
|
||||
* following properties:.
|
||||
* <LI> 1 arguments: Registry
|
||||
* <LI> 0 arguments: Empty Constructor
|
||||
* <BR>
|
||||
* <BR>It is also important the method getFactoryID() is overridden so that it returns PrimDockableFactory.ID
|
||||
*/
|
||||
public interface PrimDock extends DockElement
|
||||
{
|
||||
/**
|
||||
* Returns the PrimConfig associated with the Dockable
|
||||
* @return
|
||||
*/
|
||||
public abstract PrimConfig getConfiguration();
|
||||
|
||||
/**
|
||||
* Configures the Dockable with the aConfig
|
||||
* @return
|
||||
*/
|
||||
public abstract void setConfiguration(PrimConfig aConfig);
|
||||
|
||||
// @Override
|
||||
// public String getFactoryID()
|
||||
// {
|
||||
// return PrimDockableFactory.ID;
|
||||
// }
|
||||
|
||||
}
|
||||
197
src/glum/gui/dock/PrimDockFactory.java
Normal file
197
src/glum/gui/dock/PrimDockFactory.java
Normal file
@@ -0,0 +1,197 @@
|
||||
package glum.gui.dock;
|
||||
|
||||
import glum.reflect.ReflectUtil;
|
||||
import glum.registry.Registry;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.common.collect.BiMap;
|
||||
import com.google.common.collect.HashBiMap;
|
||||
import bibliothek.gui.Dockable;
|
||||
import bibliothek.gui.dock.DockFactory;
|
||||
import bibliothek.gui.dock.dockable.DefaultDockablePerspective;
|
||||
import bibliothek.gui.dock.layout.LocationEstimationMap;
|
||||
import bibliothek.gui.dock.perspective.PerspectiveDockable;
|
||||
import bibliothek.gui.dock.station.support.PlaceholderStrategy;
|
||||
import bibliothek.util.xml.XElement;
|
||||
|
||||
/**
|
||||
* Generic DockableFactory for creating PrimDocks.
|
||||
* <P>
|
||||
* Note that before this factory is used all PrimDockable class types must first be associated with a spawnName. This is
|
||||
* used during serialization configuration associated with PrimDock. See method {@link PrimDockFactory#addSpawnMapping}
|
||||
*/
|
||||
public class PrimDockFactory implements DockFactory<PrimDock, DefaultDockablePerspective, PrimConfig>
|
||||
{
|
||||
// Constants
|
||||
public static final String ID = "PrimDockFactory";
|
||||
public static final String SpawnNameKey = "factory.spawnName";
|
||||
|
||||
// State var
|
||||
protected Registry refRegistry;
|
||||
protected BiMap<String, Class<? extends PrimDock>> spawnMap;
|
||||
|
||||
public PrimDockFactory(Registry aRegistry)
|
||||
{
|
||||
refRegistry = aRegistry;
|
||||
spawnMap = HashBiMap.create();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a mapping for a PrimDockable to a the associated spawnName. It is mandatory
|
||||
* that this mapping is always the same regardless of application executions, as
|
||||
* this value will be serialized to the disk.
|
||||
*/
|
||||
public void addSpawnMapping(String spawnName, Class<? extends PrimDock> spawnClass)
|
||||
{
|
||||
// Ensure the spawnName is not already reserved
|
||||
if (spawnMap.containsKey(spawnName) == true)
|
||||
throw new RuntimeException("Previous mapping stored for spawnName:" + spawnName);
|
||||
|
||||
// Ensure the spawnClass is not already stored
|
||||
if (spawnMap.inverse().containsKey(spawnClass) == true)
|
||||
throw new RuntimeException("Previous mapping stored for spawnClass:" + spawnClass);
|
||||
|
||||
spawnMap.put(spawnName, spawnClass);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getID()
|
||||
{
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PrimConfig getLayout(PrimDock aDockable, Map<Dockable, Integer> children)
|
||||
{
|
||||
PrimConfig rConfig;
|
||||
String spawnName;
|
||||
|
||||
rConfig = aDockable.getConfiguration();
|
||||
|
||||
// Store the associated spawnName used to instantiate the Dockable
|
||||
spawnName = spawnMap.inverse().get(aDockable.getClass());
|
||||
if (spawnName == null)
|
||||
throw new RuntimeException("Factory is not configured properly. Failed to locate associated spawnName for class:" + aDockable.getClass());
|
||||
|
||||
// Ensure that the SpawnNameKey is not already reserved.
|
||||
; // TODO
|
||||
|
||||
rConfig.setString(SpawnNameKey, spawnName);
|
||||
return rConfig;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PrimConfig getPerspectiveLayout(DefaultDockablePerspective element, Map<PerspectiveDockable, Integer> children)
|
||||
{
|
||||
// Perspectives are not supported
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLayout(PrimDock aDockable, PrimConfig aLayout, Map<Integer, Dockable> children, PlaceholderStrategy placeholders)
|
||||
{
|
||||
aDockable.setConfiguration(aLayout);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLayout(PrimDock aDockable, PrimConfig aLayout, PlaceholderStrategy placeholders)
|
||||
{
|
||||
aDockable.setConfiguration(aLayout);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(PrimConfig aLayout, DataOutputStream aStream) throws IOException
|
||||
{
|
||||
aLayout.writeBin(aStream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(PrimConfig layout, XElement element)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PrimConfig read(DataInputStream aStream, PlaceholderStrategy placeholders) throws IOException
|
||||
{
|
||||
PrimConfig rLayout;
|
||||
|
||||
rLayout = new PrimConfig();
|
||||
rLayout.readBin(aStream);
|
||||
return rLayout;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PrimConfig read(XElement element, PlaceholderStrategy placeholders)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void estimateLocations(PrimConfig layout, LocationEstimationMap children)
|
||||
{
|
||||
; // Nothing to do
|
||||
}
|
||||
|
||||
@Override
|
||||
public PrimDock layout(PrimConfig layout, Map<Integer, Dockable> children, PlaceholderStrategy placeholders)
|
||||
{
|
||||
PrimDock aDockable;
|
||||
|
||||
aDockable = layout(layout, placeholders);
|
||||
return aDockable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PrimDock layout(PrimConfig aLayout, PlaceholderStrategy placeholders)
|
||||
{
|
||||
PrimDock rDockable;
|
||||
Class<? extends PrimDock> spawnClass;
|
||||
Constructor<? extends PrimDock>spawnConstructor;
|
||||
Class<?> parmTypes[] = {Registry.class};
|
||||
Object parmValues[] = {refRegistry};
|
||||
String spawnName;
|
||||
|
||||
spawnName = aLayout.getString(SpawnNameKey, null);
|
||||
|
||||
spawnClass = spawnMap.get(spawnName);
|
||||
if (spawnClass == null)
|
||||
throw new RuntimeException("Factory is not configured properly. Failed to locate associated class for spawn name:" + spawnName);
|
||||
|
||||
try
|
||||
{
|
||||
spawnConstructor = ReflectUtil.getConstructorSafe(spawnClass, parmTypes);
|
||||
if (spawnConstructor != null)
|
||||
rDockable = spawnConstructor.newInstance(parmValues);
|
||||
else
|
||||
rDockable = spawnClass.newInstance();
|
||||
}
|
||||
catch (Exception aExp)
|
||||
{
|
||||
throw new RuntimeException("Failed to instantite class.", aExp);
|
||||
}
|
||||
|
||||
rDockable.setConfiguration(aLayout);
|
||||
return rDockable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DefaultDockablePerspective layoutPerspective(PrimConfig layout, Map<Integer, PerspectiveDockable> children)
|
||||
{
|
||||
// Perspectives are not supported
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void layoutPerspective(DefaultDockablePerspective perspective, PrimConfig layout, Map<Integer, PerspectiveDockable> children)
|
||||
{
|
||||
; // Nothing to do
|
||||
}
|
||||
|
||||
}
|
||||
27
src/glum/gui/dock/PrimDockable.java
Normal file
27
src/glum/gui/dock/PrimDockable.java
Normal file
@@ -0,0 +1,27 @@
|
||||
package glum.gui.dock;
|
||||
|
||||
import bibliothek.gui.dock.DefaultDockable;
|
||||
|
||||
/**
|
||||
* Base class for Dockables which would like to store their configuration via
|
||||
* the PrimConfig mechanism. Note if the child class will be loaded with the
|
||||
* PrimDockableFactory, then you should have a constructor with one of the
|
||||
* following properties:.
|
||||
* <LI> 1 arguments: Registry
|
||||
* <LI> 0 arguments: Empty Constructor
|
||||
*/
|
||||
public abstract class PrimDockable extends DefaultDockable implements PrimDock
|
||||
{
|
||||
@Override
|
||||
public abstract PrimConfig getConfiguration();
|
||||
|
||||
@Override
|
||||
public abstract void setConfiguration(PrimConfig aConfig);
|
||||
|
||||
@Override
|
||||
public String getFactoryID()
|
||||
{
|
||||
return PrimDockFactory.ID;
|
||||
}
|
||||
|
||||
}
|
||||
10
src/glum/gui/dock/action/Closeable.java
Normal file
10
src/glum/gui/dock/action/Closeable.java
Normal file
@@ -0,0 +1,10 @@
|
||||
package glum.gui.dock.action;
|
||||
|
||||
public interface Closeable
|
||||
{
|
||||
/**
|
||||
* Notification method sent when this object should be closed
|
||||
*/
|
||||
public void close();
|
||||
|
||||
}
|
||||
10
src/glum/gui/dock/action/Destroyable.java
Normal file
10
src/glum/gui/dock/action/Destroyable.java
Normal file
@@ -0,0 +1,10 @@
|
||||
package glum.gui.dock.action;
|
||||
|
||||
public interface Destroyable
|
||||
{
|
||||
/**
|
||||
* Notification method sent when this object should be destroyed and all associated references should be released.
|
||||
*/
|
||||
public void destroy();
|
||||
|
||||
}
|
||||
46
src/glum/gui/dock/action/DismissAction.java
Normal file
46
src/glum/gui/dock/action/DismissAction.java
Normal file
@@ -0,0 +1,46 @@
|
||||
package glum.gui.dock.action;
|
||||
|
||||
import javax.swing.Icon;
|
||||
|
||||
import bibliothek.gui.DockStation;
|
||||
import bibliothek.gui.Dockable;
|
||||
import bibliothek.gui.dock.action.actions.SimpleButtonAction;
|
||||
|
||||
/**
|
||||
* A DockAction that will dismiss the targeted Dockable. If the targeted Dockable is a Destroyable, then is's destroy
|
||||
* method will be called. If the targeted Dockable is a Closeable then it's close method is called. As a last resort the
|
||||
* Dockable will just be hidden by removing it from it's parent. This should effectively hide the Dockable.
|
||||
*/
|
||||
public class DismissAction extends SimpleButtonAction
|
||||
{
|
||||
public DismissAction(String aText, Icon aIcon)
|
||||
{
|
||||
setText(aText);
|
||||
setIcon(aIcon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void action(Dockable aDockable)
|
||||
{
|
||||
DockStation aStation;
|
||||
|
||||
super.action(aDockable);
|
||||
|
||||
// Destroy the Destroyable
|
||||
if (aDockable instanceof Destroyable)
|
||||
{
|
||||
((Destroyable)aDockable).destroy();
|
||||
}
|
||||
// Close the Closable
|
||||
else if (aDockable instanceof Closeable)
|
||||
{
|
||||
((Closeable)aDockable).close();
|
||||
}
|
||||
// Remove the Dockable from it's parent (last resort)
|
||||
else
|
||||
{
|
||||
aStation = aDockable.getDockParent();
|
||||
aStation.drag(aDockable);
|
||||
}
|
||||
}
|
||||
}
|
||||
33
src/glum/gui/dock/action/MakeVisibleAction.java
Normal file
33
src/glum/gui/dock/action/MakeVisibleAction.java
Normal file
@@ -0,0 +1,33 @@
|
||||
package glum.gui.dock.action;
|
||||
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.JComponent;
|
||||
|
||||
import bibliothek.gui.Dockable;
|
||||
import bibliothek.gui.dock.action.actions.SimpleButtonAction;
|
||||
|
||||
/**
|
||||
* A DockAction that will cause the target component to become visible. This action is useful to bring up a
|
||||
* configuration panel related to the Dockable.
|
||||
*/
|
||||
public class MakeVisibleAction extends SimpleButtonAction
|
||||
{
|
||||
private JComponent targComp;
|
||||
|
||||
public MakeVisibleAction(JComponent aTargetComp, String aText, Icon aIcon)
|
||||
{
|
||||
targComp = aTargetComp;
|
||||
|
||||
setText(aText);
|
||||
setIcon(aIcon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void action(Dockable aDockable)
|
||||
{
|
||||
super.action(aDockable);
|
||||
|
||||
// Make the component visible
|
||||
targComp.setVisible(true);
|
||||
}
|
||||
}
|
||||
33
src/glum/gui/dock/action/SimpleDockAction.java
Normal file
33
src/glum/gui/dock/action/SimpleDockAction.java
Normal file
@@ -0,0 +1,33 @@
|
||||
package glum.gui.dock.action;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
|
||||
import javax.swing.Action;
|
||||
import javax.swing.Icon;
|
||||
|
||||
import bibliothek.gui.Dockable;
|
||||
import bibliothek.gui.dock.action.actions.SimpleButtonAction;
|
||||
|
||||
/**
|
||||
* An DockAction that will fire trigger an embedded java.awt Action
|
||||
*/
|
||||
public class SimpleDockAction extends SimpleButtonAction
|
||||
{
|
||||
protected Action refAction;
|
||||
|
||||
public SimpleDockAction(Action aAction, String aText, Icon aIcon)
|
||||
{
|
||||
refAction = aAction;
|
||||
|
||||
setText(aText);
|
||||
setIcon(aIcon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void action(Dockable dockable)
|
||||
{
|
||||
super.action(dockable);
|
||||
|
||||
refAction.actionPerformed(new ActionEvent(this, 0, "SimpleDockAction"));
|
||||
}
|
||||
}
|
||||
66
src/glum/gui/dock/action/ToggleAction.java
Normal file
66
src/glum/gui/dock/action/ToggleAction.java
Normal file
@@ -0,0 +1,66 @@
|
||||
package glum.gui.dock.action;
|
||||
|
||||
import javax.swing.Icon;
|
||||
|
||||
import bibliothek.gui.Dockable;
|
||||
import bibliothek.gui.dock.action.actions.SimpleButtonAction;
|
||||
|
||||
/**
|
||||
* An DockAction that will fire trigger an embedded java.awt Action
|
||||
*/
|
||||
public class ToggleAction extends SimpleButtonAction
|
||||
{
|
||||
// State vars
|
||||
protected boolean isActive;
|
||||
|
||||
// Gui vars
|
||||
protected Icon falseIcon, trueIcon;
|
||||
|
||||
public ToggleAction(String aText, Icon aFalseIcon, Icon aTrueIcon, boolean aIsActive)
|
||||
{
|
||||
super();
|
||||
|
||||
isActive = aIsActive;
|
||||
|
||||
falseIcon = aFalseIcon;
|
||||
trueIcon = aTrueIcon;
|
||||
|
||||
setText(aText);
|
||||
updateGui();
|
||||
}
|
||||
|
||||
/**
|
||||
* Accessor methods
|
||||
*/
|
||||
public boolean getIsActive()
|
||||
{
|
||||
return isActive;
|
||||
}
|
||||
|
||||
public void setIsActive(boolean aBool)
|
||||
{
|
||||
isActive = aBool;
|
||||
updateGui();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void action(Dockable aDockable)
|
||||
{
|
||||
isActive = !isActive;
|
||||
updateGui();
|
||||
|
||||
super.action(aDockable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method
|
||||
*/
|
||||
private void updateGui()
|
||||
{
|
||||
if (isActive == true)
|
||||
setIcon(trueIcon);
|
||||
else
|
||||
setIcon(falseIcon);
|
||||
}
|
||||
|
||||
}
|
||||
105
src/glum/gui/dock/alt/AltScreenDockFrame.java
Normal file
105
src/glum/gui/dock/alt/AltScreenDockFrame.java
Normal file
@@ -0,0 +1,105 @@
|
||||
package glum.gui.dock.alt;
|
||||
|
||||
import glum.gui.dock.action.Destroyable;
|
||||
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.awt.event.WindowListener;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JFrame;
|
||||
|
||||
import bibliothek.gui.DockFrontend;
|
||||
import bibliothek.gui.DockStation;
|
||||
import bibliothek.gui.Dockable;
|
||||
import bibliothek.gui.dock.ScreenDockStation;
|
||||
import bibliothek.gui.dock.station.screen.ScreenDockFrame;
|
||||
|
||||
public class AltScreenDockFrame extends ScreenDockFrame implements WindowListener
|
||||
{
|
||||
private DockFrontend refFrontend;
|
||||
private JFrame frame;
|
||||
|
||||
/**
|
||||
* Creates a new ScroonDockWindow with an associated JFrame.
|
||||
*
|
||||
* @param aStation
|
||||
* the station to which this dialog is responsible
|
||||
* @param isUndecorated
|
||||
* whether the dialog should suppress the default decorations
|
||||
*/
|
||||
public AltScreenDockFrame(DockFrontend aFrontend, ScreenDockStation aStation, boolean isUndecorated)
|
||||
{
|
||||
super(aStation, isUndecorated);
|
||||
|
||||
refFrontend = aFrontend;
|
||||
|
||||
// Set up the Jframe
|
||||
frame = getFrame();
|
||||
frame.addWindowListener(this);
|
||||
frame.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowOpened(WindowEvent e)
|
||||
{
|
||||
; // Nothing to do
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowClosing(WindowEvent e)
|
||||
{
|
||||
Dockable dockable;
|
||||
|
||||
System.out.println("Window should be closed....");
|
||||
dockable = getDockable();
|
||||
|
||||
// Destroy the associated Destroyable
|
||||
if (dockable instanceof Destroyable)
|
||||
{
|
||||
((Destroyable)dockable).destroy();
|
||||
}
|
||||
// Attempt to hide the (if it is registered) Dockable
|
||||
else if (refFrontend != null && refFrontend.listDockables().contains(dockable) == true)
|
||||
{
|
||||
refFrontend.hide(dockable);
|
||||
}
|
||||
// Just hide the dockable
|
||||
else
|
||||
{
|
||||
DockStation aStation;
|
||||
|
||||
aStation = dockable.getDockParent();
|
||||
aStation.drag(dockable);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowClosed(WindowEvent e)
|
||||
{
|
||||
; // Nothing to do
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowIconified(WindowEvent e)
|
||||
{
|
||||
; // Nothing to do
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowDeiconified(WindowEvent e)
|
||||
{
|
||||
; // Nothing to do
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowActivated(WindowEvent e)
|
||||
{
|
||||
; // Nothing to do
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowDeactivated(WindowEvent e)
|
||||
{
|
||||
; // Nothing to do
|
||||
}
|
||||
|
||||
}
|
||||
117
src/glum/gui/dock/alt/AltScreenDockStation.java
Normal file
117
src/glum/gui/dock/alt/AltScreenDockStation.java
Normal file
@@ -0,0 +1,117 @@
|
||||
package glum.gui.dock.alt;
|
||||
|
||||
import glum.gui.dock.BaseDockable;
|
||||
|
||||
import java.awt.Window;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
import bibliothek.gui.Dockable;
|
||||
import bibliothek.gui.dock.ScreenDockStation;
|
||||
import bibliothek.gui.dock.action.DefaultDockActionSource;
|
||||
import bibliothek.gui.dock.action.DockAction;
|
||||
import bibliothek.gui.dock.action.DockActionSource;
|
||||
import bibliothek.gui.dock.action.LocationHint;
|
||||
|
||||
/**
|
||||
* Alternative ScreenDockStation which provides no default direct/indirect action offers.
|
||||
*/
|
||||
public class AltScreenDockStation extends ScreenDockStation
|
||||
{
|
||||
// Action vars
|
||||
private List<DockAction> directDockActionList;
|
||||
private List<DockAction> indirectDockActionList;
|
||||
|
||||
// Lock vars
|
||||
private Set<Dockable> lockSet;
|
||||
private boolean isLocked;
|
||||
|
||||
public AltScreenDockStation(Window owner)
|
||||
{
|
||||
super(owner);
|
||||
|
||||
directDockActionList = Lists.newArrayList();
|
||||
indirectDockActionList = Lists.newArrayList();
|
||||
|
||||
lockSet = Sets.newHashSet();
|
||||
isLocked = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a DockAction to always be available for direct Dockables
|
||||
*/
|
||||
public void addDirectActionOffer(DockAction aDockAction)
|
||||
{
|
||||
directDockActionList.add(aDockAction);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a DockAction to always be available for indirect Dockables
|
||||
*/
|
||||
public void addIndirectActionOffer(DockAction aDockAction)
|
||||
{
|
||||
indirectDockActionList.add(aDockAction);
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to force this station to accept no further Dockables. Only dockables that are currently children
|
||||
* will be accepted.
|
||||
*/
|
||||
public void lockStation(boolean aBool)
|
||||
{
|
||||
isLocked = aBool;
|
||||
|
||||
if (isLocked == false)
|
||||
{
|
||||
lockSet.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
// Record all of the valid children when the lock is triggered
|
||||
for (int c1 = 0; c1 < getDockableCount(); c1++)
|
||||
{
|
||||
lockSet.add(getDockable(c1));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept(Dockable aChild)
|
||||
{
|
||||
// If we are locked then never accept any Dockable, which was not recorded as valid when the lock happened
|
||||
if (isLocked == true && lockSet.contains(aChild) == false)
|
||||
return false;
|
||||
|
||||
// Never accept any Dockable that has been marked as nontransferable
|
||||
if (aChild instanceof BaseDockable)
|
||||
return ((BaseDockable)aChild).isTransferable(this);
|
||||
|
||||
return super.accept(aChild);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DefaultDockActionSource getDirectActionOffers(Dockable dockable)
|
||||
{
|
||||
DefaultDockActionSource source;
|
||||
|
||||
source = new DefaultDockActionSource(new LocationHint(LocationHint.DIRECT_ACTION, LocationHint.VERY_RIGHT));
|
||||
source.add(directDockActionList.toArray(new DockAction[0]));
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DockActionSource getIndirectActionOffers(Dockable dockable)
|
||||
{
|
||||
DefaultDockActionSource source;
|
||||
|
||||
source = new DefaultDockActionSource(new LocationHint(LocationHint.INDIRECT_ACTION, LocationHint.VERY_RIGHT));
|
||||
source.add(indirectDockActionList.toArray(new DockAction[0]));
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
}
|
||||
69
src/glum/gui/dock/alt/AltScreenDockWindowFactory.java
Normal file
69
src/glum/gui/dock/alt/AltScreenDockWindowFactory.java
Normal file
@@ -0,0 +1,69 @@
|
||||
package glum.gui.dock.alt;
|
||||
|
||||
import java.awt.Dialog;
|
||||
import java.awt.Frame;
|
||||
import java.awt.Window;
|
||||
|
||||
import javax.swing.Icon;
|
||||
|
||||
import bibliothek.gui.DockFrontend;
|
||||
import bibliothek.gui.dock.ScreenDockStation;
|
||||
import bibliothek.gui.dock.station.screen.AbstractScreenDockWindow;
|
||||
import bibliothek.gui.dock.station.screen.DefaultScreenDockWindowFactory;
|
||||
import bibliothek.gui.dock.station.screen.ScreenDockDialog;
|
||||
import bibliothek.gui.dock.station.screen.ScreenDockWindow;
|
||||
|
||||
/**
|
||||
* Alternative ScreenDockWindowFactory that return AltScreenDockFrame instead of DefaultScreenDockFrame. Also the
|
||||
* returned windows will by default have the typical OS decorations.
|
||||
*/
|
||||
public class AltScreenDockWindowFactory extends DefaultScreenDockWindowFactory
|
||||
{
|
||||
private DockFrontend refFrontend;
|
||||
|
||||
public AltScreenDockWindowFactory(DockFrontend aFrontend)
|
||||
{
|
||||
refFrontend = aFrontend;
|
||||
|
||||
setKind(Kind.FRAME);
|
||||
setUndecorated(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScreenDockWindow createWindow(ScreenDockStation station)
|
||||
{
|
||||
Kind kind;
|
||||
boolean undecorated;
|
||||
boolean showDockTitle;
|
||||
Icon titleIcon;
|
||||
String titleText;
|
||||
|
||||
kind = getKind();
|
||||
undecorated = isUndecorated();
|
||||
showDockTitle = isShowDockTitle();
|
||||
titleIcon = getTitleIcon();
|
||||
titleText = getTitleText();
|
||||
|
||||
AbstractScreenDockWindow window;
|
||||
|
||||
if (kind == Kind.FRAME)
|
||||
{
|
||||
window = new AltScreenDockFrame(refFrontend, station, undecorated);
|
||||
}
|
||||
else
|
||||
{
|
||||
Window owner = station.getOwner();
|
||||
if (owner instanceof Frame)
|
||||
window = new ScreenDockDialog(station, (Frame)owner, undecorated);
|
||||
else if (owner instanceof Dialog)
|
||||
window = new ScreenDockDialog(station, (Dialog)owner, undecorated);
|
||||
else
|
||||
window = new ScreenDockDialog(station, undecorated);
|
||||
}
|
||||
|
||||
window.setShowTitle(showDockTitle);
|
||||
window.setTitleIcon(titleIcon);
|
||||
window.setTitleText(titleText);
|
||||
return window;
|
||||
}
|
||||
}
|
||||
176
src/glum/gui/dock/alt/AltSplitDockStation.java
Normal file
176
src/glum/gui/dock/alt/AltSplitDockStation.java
Normal file
@@ -0,0 +1,176 @@
|
||||
package glum.gui.dock.alt;
|
||||
|
||||
import glum.gui.dock.BaseDockable;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
import bibliothek.gui.Dockable;
|
||||
import bibliothek.gui.dock.SplitDockStation;
|
||||
import bibliothek.gui.dock.action.DefaultDockActionSource;
|
||||
import bibliothek.gui.dock.action.DockAction;
|
||||
import bibliothek.gui.dock.action.DockActionSource;
|
||||
import bibliothek.gui.dock.action.LocationHint;
|
||||
|
||||
public class AltSplitDockStation extends SplitDockStation
|
||||
{
|
||||
// Action vars
|
||||
private List<DockAction> directDockActionList;
|
||||
private List<DockAction> localDockActionList;
|
||||
private List<DockAction> indirectDockActionList;
|
||||
|
||||
// Lock vars
|
||||
private Set<Dockable> lockSet;
|
||||
private boolean isLocked;
|
||||
|
||||
public AltSplitDockStation()
|
||||
{
|
||||
super();
|
||||
|
||||
directDockActionList = Lists.newArrayList();
|
||||
localDockActionList = Lists.newArrayList();
|
||||
indirectDockActionList = Lists.newArrayList();
|
||||
|
||||
lockSet = Sets.newHashSet();
|
||||
isLocked = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a DockAction to always be available for direct Dockables
|
||||
*/
|
||||
public void addDirectActionOffer(DockAction aDockAction)
|
||||
{
|
||||
directDockActionList.add(aDockAction);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a DockAction to always be available for local Dockables
|
||||
*/
|
||||
public void addLocalActionOffer(DockAction aDockAction)
|
||||
{
|
||||
localDockActionList.add(aDockAction);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a DockAction to always be available for indirect Dockables
|
||||
*/
|
||||
public void addIndirectActionOffer(DockAction aDockAction)
|
||||
{
|
||||
indirectDockActionList.add(aDockAction);
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to force this station to accept no further Dockables. Only dockables that are currently children
|
||||
* will be accepted.
|
||||
*/
|
||||
public void lockStation(boolean aBool)
|
||||
{
|
||||
isLocked = aBool;
|
||||
|
||||
if (isLocked == false)
|
||||
{
|
||||
lockSet.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
// Record all of the valid children when the lock is triggered
|
||||
for (int c1 = 0; c1 < getDockableCount(); c1++)
|
||||
{
|
||||
lockSet.add(getDockable(c1));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept(Dockable aChild)
|
||||
{
|
||||
// If we are locked then never accept any Dockable, which was not recorded as valid when the lock happened
|
||||
if (isLocked == true && lockSet.contains(aChild) == false)
|
||||
return false;
|
||||
|
||||
// Never accept any Dockable that has been marked as nontransferable
|
||||
if (aChild instanceof BaseDockable)
|
||||
return ((BaseDockable)aChild).isTransferable(this);
|
||||
|
||||
// Default behavior for non BaseDockables
|
||||
return super.accept(aChild);
|
||||
}
|
||||
|
||||
//
|
||||
// @Override
|
||||
// protected boolean acceptable(Dockable old, Dockable next)
|
||||
// {
|
||||
// return false;
|
||||
//// // Never accept any Dockable that has been marked as nontransferable
|
||||
//// if (old instanceof BaseDockable || next instanceof BaseDockable)
|
||||
//// {
|
||||
//// if (((BaseDockable)old).isTransferable() == false)
|
||||
//// return false;
|
||||
////
|
||||
//// if (((BaseDockable)next).isTransferable() == false)
|
||||
//// return false;
|
||||
//// }
|
||||
////
|
||||
////
|
||||
//// // TODO Auto-generated method stub
|
||||
//// return super.acceptable(old, next);
|
||||
// }
|
||||
|
||||
// @Override
|
||||
// public boolean canDrag(Dockable aDockable)
|
||||
// {
|
||||
// if (lockSet.contains(aDockable) == true)
|
||||
// return false;
|
||||
//
|
||||
// return super.canDrag(aDockable);
|
||||
// }
|
||||
//
|
||||
//
|
||||
// @Override
|
||||
// public boolean canReplace(Dockable oldDockable, Dockable nextDockable)
|
||||
// {
|
||||
// if (lockSet.contains(oldDockable) == true)
|
||||
// return false;
|
||||
//
|
||||
// if (lockSet.contains(nextDockable) == true)
|
||||
// return false;
|
||||
//
|
||||
// return super.canReplace(oldDockable, nextDockable);
|
||||
// }
|
||||
|
||||
@Override
|
||||
public DefaultDockActionSource getDirectActionOffers(Dockable dockable)
|
||||
{
|
||||
DefaultDockActionSource source;
|
||||
|
||||
source = new DefaultDockActionSource(new LocationHint(LocationHint.DIRECT_ACTION, LocationHint.VERY_RIGHT));
|
||||
source.add(directDockActionList.toArray(new DockAction[0]));
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DockActionSource getLocalActionOffers()
|
||||
{
|
||||
DefaultDockActionSource source;
|
||||
|
||||
source = new DefaultDockActionSource(new LocationHint(LocationHint.DOCKABLE, LocationHint.RIGHT));
|
||||
source.add(localDockActionList.toArray(new DockAction[0]));
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DockActionSource getIndirectActionOffers(Dockable dockable)
|
||||
{
|
||||
DefaultDockActionSource source;
|
||||
|
||||
source = new DefaultDockActionSource(new LocationHint(LocationHint.INDIRECT_ACTION, LocationHint.VERY_RIGHT));
|
||||
source.add(indirectDockActionList.toArray(new DockAction[0]));
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
}
|
||||
50
src/glum/gui/document/BaseDocument.java
Normal file
50
src/glum/gui/document/BaseDocument.java
Normal file
@@ -0,0 +1,50 @@
|
||||
package glum.gui.document;
|
||||
|
||||
import java.awt.event.*;
|
||||
import javax.swing.text.*;
|
||||
import javax.swing.JTextField;
|
||||
|
||||
public abstract class BaseDocument extends PlainDocument implements ActionListener, FocusListener
|
||||
{
|
||||
// State vars
|
||||
protected JTextField ownerTF;
|
||||
|
||||
public BaseDocument(JTextField aOwnerTF)
|
||||
{
|
||||
super();
|
||||
|
||||
ownerTF = aOwnerTF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the owner of this Document model
|
||||
* Todo: This method should no longer be needed.
|
||||
*/
|
||||
public JTextField getOwner()
|
||||
{
|
||||
return ownerTF;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e)
|
||||
{
|
||||
formalizeInput();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void focusGained(FocusEvent e)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void focusLost(FocusEvent e)
|
||||
{
|
||||
formalizeInput();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the text to reflect a formal output
|
||||
*/
|
||||
public abstract void formalizeInput();
|
||||
|
||||
}
|
||||
61
src/glum/gui/document/BaseNumberDocument.java
Normal file
61
src/glum/gui/document/BaseNumberDocument.java
Normal file
@@ -0,0 +1,61 @@
|
||||
package glum.gui.document;
|
||||
|
||||
import javax.swing.JTextField;
|
||||
|
||||
public abstract class BaseNumberDocument extends BaseDocument
|
||||
{
|
||||
// State vars
|
||||
protected double minVal, maxVal;
|
||||
protected boolean formalizeDoc;
|
||||
protected int numAvailCols;
|
||||
|
||||
public BaseNumberDocument(JTextField aOwner, double aMinVal, double aMaxVal)
|
||||
{
|
||||
super(aOwner);
|
||||
|
||||
setMinMaxValue(aMinVal, aMaxVal);
|
||||
formalizeDoc = false;
|
||||
numAvailCols = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the new range of valid numbers.
|
||||
*/
|
||||
public void setMinMaxValue(double aMinVal, double aMaxVal)
|
||||
{
|
||||
minVal = aMinVal;
|
||||
maxVal = aMaxVal;
|
||||
|
||||
// Insanity check
|
||||
if (minVal >= maxVal)
|
||||
throw new RuntimeException("Illogical range. Range: [" + minVal + "," + maxVal + "]");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void formalizeInput()
|
||||
{
|
||||
String currStr;
|
||||
|
||||
// Insanity check
|
||||
if (ownerTF == null)
|
||||
return;
|
||||
|
||||
// Is formalization required
|
||||
if (formalizeDoc == false)
|
||||
return;
|
||||
|
||||
// Disassociate ourselves from event handling
|
||||
ownerTF.removeActionListener(this);
|
||||
ownerTF.removeFocusListener(this);
|
||||
|
||||
currStr = ownerTF.getText();
|
||||
ownerTF.setText(currStr);
|
||||
|
||||
// Reassociate ourselves from event handling
|
||||
ownerTF.addActionListener(this);
|
||||
ownerTF.addFocusListener(this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
65
src/glum/gui/document/CharDocument.java
Normal file
65
src/glum/gui/document/CharDocument.java
Normal file
@@ -0,0 +1,65 @@
|
||||
package glum.gui.document;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.text.AttributeSet;
|
||||
import javax.swing.text.BadLocationException;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
/**
|
||||
* Specialized Document designed to accept only the specified input chars
|
||||
*/
|
||||
public class CharDocument extends BaseDocument
|
||||
{
|
||||
private Set<Character> validSet;
|
||||
|
||||
public CharDocument(JTextField aOwner, String validCharStr)
|
||||
{
|
||||
this(aOwner, validCharStr, true);
|
||||
}
|
||||
|
||||
public CharDocument(JTextField aOwner, String validCharStr, boolean isCaseSensitive)
|
||||
{
|
||||
super(aOwner);
|
||||
|
||||
validSet = Sets.newHashSet();
|
||||
for (int c1 = 0; c1 < validCharStr.length(); c1++)
|
||||
{
|
||||
validSet.add(validCharStr.charAt(c1));
|
||||
if (isCaseSensitive == false)
|
||||
{
|
||||
validSet.add(Character.toLowerCase(validCharStr.charAt(c1)));
|
||||
validSet.add(Character.toUpperCase(validCharStr.charAt(c1)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void formalizeInput()
|
||||
{
|
||||
; // Nothing to do
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insertString(int offs, String str, AttributeSet a) throws BadLocationException
|
||||
{
|
||||
char aChar;
|
||||
|
||||
// Insanity check
|
||||
if (str == null)
|
||||
return;
|
||||
|
||||
// Ensure all of the characters in str are in the valid set
|
||||
for (int c1 = 0; c1 < str.length(); c1++)
|
||||
{
|
||||
aChar = str.charAt(c1);
|
||||
if (validSet.contains(aChar) == false)
|
||||
throw new BadLocationException("Invalid character: " + aChar, offs);
|
||||
}
|
||||
|
||||
super.insertString(offs, str, a);
|
||||
}
|
||||
|
||||
}
|
||||
109
src/glum/gui/document/NumberDocument.java
Normal file
109
src/glum/gui/document/NumberDocument.java
Normal file
@@ -0,0 +1,109 @@
|
||||
package glum.gui.document;
|
||||
|
||||
import javax.swing.text.*;
|
||||
import javax.swing.JTextField;
|
||||
|
||||
import glum.gui.GuiUtil;
|
||||
|
||||
public class NumberDocument extends BaseNumberDocument
|
||||
{
|
||||
protected boolean allowFloats;
|
||||
// protected NumberUnit myUnit;
|
||||
|
||||
public NumberDocument(JTextField aOwnerTF, boolean aFormalizeDoc)
|
||||
{
|
||||
super(aOwnerTF, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY);
|
||||
|
||||
allowFloats = true;
|
||||
|
||||
formalizeDoc = aFormalizeDoc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets in whether floating point numbers are allowed
|
||||
*/
|
||||
public void setAllowFloats(boolean aBool)
|
||||
{
|
||||
allowFloats = aBool;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insertString(int offs, String str, AttributeSet a) throws BadLocationException
|
||||
{
|
||||
String bStr, eStr, resultStr;
|
||||
double aVal;
|
||||
char aChar;
|
||||
|
||||
// Insanity check
|
||||
if (str == null)
|
||||
return;
|
||||
|
||||
// Special cases
|
||||
aChar = str.charAt(0);
|
||||
if (offs == 0)
|
||||
{
|
||||
// Reject if we need a positive number
|
||||
if (aChar == '-' && minVal >= 0)
|
||||
{
|
||||
throw new BadLocationException("Negative values are not allowed.", offs);
|
||||
}
|
||||
|
||||
// Potential valid string that starts off an int
|
||||
if ((aChar == '-') && str.length() == 1)
|
||||
{
|
||||
super.insertString(offs, str, a);
|
||||
return;
|
||||
}
|
||||
|
||||
// Potential valid string that starts off a double
|
||||
if ((aChar == '.') && str.length() == 1 && allowFloats == true)
|
||||
{
|
||||
super.insertString(offs, str, a);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (offs == 1 && str.length() == 1 && aChar == '.')
|
||||
{
|
||||
// Potential valid string that starts off a double
|
||||
if ("-".equals(getText(0, offs)) == true && allowFloats == true)
|
||||
{
|
||||
super.insertString(offs, str, a);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Reject if we detect a floating point, but it is not allowed
|
||||
if (str.contains(".") == true && allowFloats == false)
|
||||
throw new BadLocationException("Only integers are allowed.", offs);
|
||||
|
||||
// Ensure we do not exceed number of columns
|
||||
if (numAvailCols > 0)
|
||||
{
|
||||
if (offs + str.length() >= numAvailCols)
|
||||
throw new BadLocationException("Too many characters to insert.", offs);
|
||||
}
|
||||
|
||||
// Form the resultant string
|
||||
bStr = "";
|
||||
eStr = "";
|
||||
if (offs > 0)
|
||||
bStr = getText(0, offs);
|
||||
eStr = getText(offs, getLength() - offs);
|
||||
resultStr = bStr + str + eStr;
|
||||
|
||||
// Ensure the resultant is sensical
|
||||
aVal = GuiUtil.readDouble(resultStr, Double.NaN);
|
||||
if (Double.isNaN(aVal) == true)
|
||||
throw new BadLocationException("Nonsensical number.", offs);
|
||||
|
||||
// Ensure that the number is in range
|
||||
if (aVal > maxVal)
|
||||
throw new BadLocationException("Out of numerical range.", offs);
|
||||
else if (aVal < minVal)
|
||||
throw new BadLocationException("Out of numerical range.", offs);
|
||||
|
||||
// Insert the string
|
||||
super.insertString(offs, str, a);
|
||||
}
|
||||
|
||||
}
|
||||
56
src/glum/gui/icon/ArrowNorthIcon.java
Normal file
56
src/glum/gui/icon/ArrowNorthIcon.java
Normal file
@@ -0,0 +1,56 @@
|
||||
package glum.gui.icon;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Polygon;
|
||||
import javax.swing.plaf.metal.MetalLookAndFeel;
|
||||
|
||||
public class ArrowNorthIcon extends BaseIcon
|
||||
{
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public ArrowNorthIcon(int aDim)
|
||||
{
|
||||
super(aDim);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintIcon(Component aComp, Graphics g, int x, int y)
|
||||
{
|
||||
Polygon aPolygon;
|
||||
int w, h;
|
||||
int hW, hH;
|
||||
|
||||
w = getIconWidth();
|
||||
h = getIconHeight();
|
||||
hW = w / 2;
|
||||
hH = h / 2;
|
||||
|
||||
g.setColor(Color.BLACK);
|
||||
if (aComp.isEnabled() == false)
|
||||
g.setColor(MetalLookAndFeel.getControlDisabled());
|
||||
|
||||
if (IconUtil.isPressed(aComp) == true)
|
||||
y += 2;
|
||||
|
||||
g.translate(x + hW, y + hH);
|
||||
|
||||
aPolygon = new Polygon();
|
||||
aPolygon.addPoint(0, -hH);
|
||||
aPolygon.addPoint(-hW, 0);
|
||||
|
||||
aPolygon.addPoint(-hW/4, 0);
|
||||
aPolygon.addPoint(-hW/4, hH);
|
||||
aPolygon.addPoint(+hW/4, hH);
|
||||
aPolygon.addPoint(+hW/4, 0);
|
||||
|
||||
aPolygon.addPoint(+hW, 0);
|
||||
|
||||
g.fillPolygon(aPolygon);
|
||||
|
||||
g.translate(-(x + hW), -(y + hH));
|
||||
}
|
||||
|
||||
}
|
||||
56
src/glum/gui/icon/ArrowSouthIcon.java
Normal file
56
src/glum/gui/icon/ArrowSouthIcon.java
Normal file
@@ -0,0 +1,56 @@
|
||||
package glum.gui.icon;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Polygon;
|
||||
import javax.swing.plaf.metal.MetalLookAndFeel;
|
||||
|
||||
public class ArrowSouthIcon extends BaseIcon
|
||||
{
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public ArrowSouthIcon(int aDim)
|
||||
{
|
||||
super(aDim);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintIcon(Component aComp, Graphics g, int x, int y)
|
||||
{
|
||||
Polygon aPolygon;
|
||||
int w, h;
|
||||
int hW, hH;
|
||||
|
||||
w = getIconWidth();
|
||||
h = getIconHeight();
|
||||
hW = w / 2;
|
||||
hH = h / 2;
|
||||
|
||||
g.setColor(Color.BLACK);
|
||||
if (aComp.isEnabled() == false)
|
||||
g.setColor(MetalLookAndFeel.getControlDisabled());
|
||||
|
||||
if (IconUtil.isPressed(aComp) == true)
|
||||
y += 2;
|
||||
|
||||
g.translate(x + hW, y + hH);
|
||||
|
||||
aPolygon = new Polygon();
|
||||
aPolygon.addPoint(0, +hH);
|
||||
aPolygon.addPoint(+hW, 0);
|
||||
|
||||
aPolygon.addPoint(+hW/4, 0);
|
||||
aPolygon.addPoint(+hW/4, -hH);
|
||||
aPolygon.addPoint(-hW/4, -hH);
|
||||
aPolygon.addPoint(-hW/4, 0);
|
||||
|
||||
aPolygon.addPoint(-hW, 0);
|
||||
|
||||
g.fillPolygon(aPolygon);
|
||||
|
||||
g.translate(-(x + hW), -(y + hH));
|
||||
}
|
||||
|
||||
}
|
||||
29
src/glum/gui/icon/BaseIcon.java
Normal file
29
src/glum/gui/icon/BaseIcon.java
Normal file
@@ -0,0 +1,29 @@
|
||||
package glum.gui.icon;
|
||||
|
||||
import javax.swing.Icon;
|
||||
|
||||
public abstract class BaseIcon implements Icon
|
||||
{
|
||||
protected int mDim;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public BaseIcon(int aDim)
|
||||
{
|
||||
mDim = aDim;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIconWidth()
|
||||
{
|
||||
return mDim;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIconHeight()
|
||||
{
|
||||
return mDim;
|
||||
}
|
||||
|
||||
}
|
||||
58
src/glum/gui/icon/DeleteIcon.java
Normal file
58
src/glum/gui/icon/DeleteIcon.java
Normal file
@@ -0,0 +1,58 @@
|
||||
package glum.gui.icon;
|
||||
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import javax.swing.plaf.metal.MetalLookAndFeel;
|
||||
|
||||
public class DeleteIcon extends BaseIcon
|
||||
{
|
||||
public DeleteIcon(int aDim)
|
||||
{
|
||||
super(aDim);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintIcon(Component aComp, Graphics g, int x, int y)
|
||||
{
|
||||
Graphics2D g2d;
|
||||
BasicStroke aStroke;
|
||||
int w, h;
|
||||
int hW, hH, dX, dY;
|
||||
int shrinkSize;
|
||||
float strokeW;
|
||||
|
||||
w = getIconWidth();
|
||||
h = getIconHeight();
|
||||
hW = w / 2;
|
||||
hH = h / 2;
|
||||
|
||||
g2d = (Graphics2D)g;
|
||||
|
||||
g2d.setColor(Color.RED.darker());
|
||||
if (aComp.isEnabled() == false)
|
||||
g2d.setColor(MetalLookAndFeel.getControlDisabled());
|
||||
|
||||
shrinkSize = 2;
|
||||
if (IconUtil.isPressed(aComp) == true)
|
||||
shrinkSize += 2;
|
||||
|
||||
g2d.translate(x + hW, y + hH);
|
||||
|
||||
|
||||
strokeW = getIconWidth() / 7.0f;
|
||||
aStroke = new BasicStroke(strokeW, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
|
||||
|
||||
g2d.setStroke(aStroke);
|
||||
|
||||
dX = hW - shrinkSize;
|
||||
dY = hH - shrinkSize;
|
||||
g2d.drawLine(-dX,-dY, +dX,+dY);
|
||||
g2d.drawLine(-dX,+dY, +dX,-dY);
|
||||
|
||||
g2d.translate(-(x + hW), -(y + hH));
|
||||
}
|
||||
|
||||
}
|
||||
36
src/glum/gui/icon/EmptyIcon.java
Normal file
36
src/glum/gui/icon/EmptyIcon.java
Normal file
@@ -0,0 +1,36 @@
|
||||
package glum.gui.icon;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics;
|
||||
|
||||
import javax.swing.Icon;
|
||||
|
||||
public class EmptyIcon implements Icon
|
||||
{
|
||||
protected int width, height;
|
||||
|
||||
EmptyIcon(int aWidth, int aHeight)
|
||||
{
|
||||
width = aWidth;
|
||||
height = aHeight;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintIcon(Component c, Graphics g, int x, int y)
|
||||
{
|
||||
; // Nothing to do
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIconWidth()
|
||||
{
|
||||
return width;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIconHeight()
|
||||
{
|
||||
return height;
|
||||
}
|
||||
|
||||
}
|
||||
35
src/glum/gui/icon/IconUtil.java
Normal file
35
src/glum/gui/icon/IconUtil.java
Normal file
@@ -0,0 +1,35 @@
|
||||
package glum.gui.icon;
|
||||
|
||||
import java.awt.Component;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JButton;
|
||||
|
||||
public class IconUtil
|
||||
{
|
||||
/**
|
||||
* Utility method to load the Icon specified by the resource path.
|
||||
*/
|
||||
public static ImageIcon loadIcon(String iconPath)
|
||||
{
|
||||
// URL aURL;
|
||||
//
|
||||
// aURL = IconUtil.class.getClassLoader().getResource(iconPath);
|
||||
// if (aURL == null)
|
||||
// throw new RuntimeException("Failed to load icon for path: " + iconPath);
|
||||
//
|
||||
// return new ImageIcon(aURL);
|
||||
return new ImageIcon(ClassLoader.getSystemResource(iconPath));
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to test if aComp is pressed down.
|
||||
*/
|
||||
public static boolean isPressed(Component aComp)
|
||||
{
|
||||
if (aComp instanceof JButton == false)
|
||||
return false;
|
||||
|
||||
return ((JButton)aComp).getModel().isPressed();
|
||||
}
|
||||
|
||||
}
|
||||
40
src/glum/gui/info/FilePathInfo.java
Normal file
40
src/glum/gui/info/FilePathInfo.java
Normal file
@@ -0,0 +1,40 @@
|
||||
package glum.gui.info;
|
||||
|
||||
import glum.zio.ZinStream;
|
||||
import glum.zio.ZoutStream;
|
||||
import glum.zio.raw.ZioRaw;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class FilePathInfo implements ZioRaw
|
||||
{
|
||||
// State vars
|
||||
protected String filePath;
|
||||
|
||||
public FilePathInfo()
|
||||
{
|
||||
filePath = null;
|
||||
}
|
||||
|
||||
public FilePathInfo(String aFilePath)
|
||||
{
|
||||
filePath = aFilePath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void zioReadRaw(ZinStream aStream) throws IOException
|
||||
{
|
||||
aStream.readVersion(0);
|
||||
|
||||
filePath = aStream.readString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void zioWriteRaw(ZoutStream aStream) throws IOException
|
||||
{
|
||||
aStream.writeVersion(0);
|
||||
|
||||
aStream.writeString(filePath);
|
||||
}
|
||||
|
||||
}
|
||||
79
src/glum/gui/info/WindowInfo.java
Normal file
79
src/glum/gui/info/WindowInfo.java
Normal file
@@ -0,0 +1,79 @@
|
||||
package glum.gui.info;
|
||||
|
||||
import glum.zio.ZinStream;
|
||||
import glum.zio.ZoutStream;
|
||||
import glum.zio.raw.ZioRaw;
|
||||
import glum.zio.util.ZioUtil;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.*;
|
||||
|
||||
public class WindowInfo implements ZioRaw
|
||||
{
|
||||
// Raw vars
|
||||
protected Point position;
|
||||
protected Dimension size;
|
||||
protected boolean isVisible;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public WindowInfo()
|
||||
{
|
||||
position = null;
|
||||
size = null;
|
||||
isVisible = false;
|
||||
}
|
||||
|
||||
public WindowInfo(Component aComponent)
|
||||
{
|
||||
this();
|
||||
|
||||
if (aComponent == null)
|
||||
return;
|
||||
|
||||
position = aComponent.getLocation();
|
||||
size = aComponent.getSize();
|
||||
isVisible = aComponent.isVisible();
|
||||
}
|
||||
|
||||
/**
|
||||
* configure - Syncs aComponent with parmaters of this WindowInfo
|
||||
*/
|
||||
public void configure(Component aComponent)
|
||||
{
|
||||
if (position != null)
|
||||
aComponent.setLocation(position);
|
||||
|
||||
if (size != null)
|
||||
{
|
||||
aComponent.setPreferredSize(size);
|
||||
aComponent.setSize(size);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void zioReadRaw(ZinStream aStream) throws IOException
|
||||
{
|
||||
aStream.readVersion(0);
|
||||
|
||||
isVisible = aStream.readBool();
|
||||
|
||||
position = ZioUtil.readPoint(aStream);
|
||||
|
||||
size = ZioUtil.readDimension(aStream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void zioWriteRaw(ZoutStream aStream) throws IOException
|
||||
{
|
||||
aStream.writeVersion(0);
|
||||
|
||||
aStream.writeBool(isVisible);
|
||||
|
||||
ZioUtil.writePoint(aStream, position);
|
||||
|
||||
ZioUtil.writeDimension(aStream, size);
|
||||
}
|
||||
|
||||
}
|
||||
75
src/glum/gui/misc/BooleanCellEditor.java
Normal file
75
src/glum/gui/misc/BooleanCellEditor.java
Normal file
@@ -0,0 +1,75 @@
|
||||
package glum.gui.misc;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedList;
|
||||
import javax.swing.AbstractCellEditor;
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.table.TableCellEditor;
|
||||
|
||||
public class BooleanCellEditor extends AbstractCellEditor implements ActionListener, TableCellEditor
|
||||
{
|
||||
// State vars
|
||||
protected Collection<ActionListener> myListeners;
|
||||
protected JCheckBox refCheckBox;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public BooleanCellEditor()
|
||||
{
|
||||
this(null);
|
||||
}
|
||||
|
||||
public BooleanCellEditor(ActionListener aListener)
|
||||
{
|
||||
myListeners = new LinkedList<ActionListener>();
|
||||
if (aListener != null)
|
||||
myListeners.add(aListener);
|
||||
|
||||
refCheckBox = new JCheckBox("", false);
|
||||
refCheckBox.addActionListener(this);
|
||||
}
|
||||
|
||||
public void addActionListener(ActionListener aListener)
|
||||
{
|
||||
myListeners.add(aListener);
|
||||
}
|
||||
|
||||
public void removeActionListener(ActionListener aListener)
|
||||
{
|
||||
myListeners.remove(aListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent aEvent)
|
||||
{
|
||||
fireEditingStopped();
|
||||
|
||||
aEvent = new ActionEvent(this, aEvent.getID(), "BooleanCell edited.");
|
||||
for (ActionListener aListener : myListeners)
|
||||
aListener.actionPerformed(aEvent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column)
|
||||
{
|
||||
// Update our checkbox with the appropriate state
|
||||
refCheckBox.removeActionListener(this);
|
||||
if (value instanceof Boolean)
|
||||
refCheckBox.setSelected((Boolean)value);
|
||||
refCheckBox.addActionListener(this);
|
||||
|
||||
return refCheckBox;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getCellEditorValue()
|
||||
{
|
||||
return refCheckBox.isSelected();
|
||||
}
|
||||
|
||||
}
|
||||
28
src/glum/gui/misc/BooleanCellRenderer.java
Normal file
28
src/glum/gui/misc/BooleanCellRenderer.java
Normal file
@@ -0,0 +1,28 @@
|
||||
package glum.gui.misc;
|
||||
|
||||
import java.awt.Component;
|
||||
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.table.TableCellRenderer;
|
||||
|
||||
public class BooleanCellRenderer extends JCheckBox implements TableCellRenderer
|
||||
{
|
||||
public BooleanCellRenderer()
|
||||
{
|
||||
super("", false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
|
||||
{
|
||||
if (value instanceof Boolean)
|
||||
{
|
||||
setSelected((Boolean)value);
|
||||
return this;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
60
src/glum/gui/misc/ColorCellRenderer.java
Normal file
60
src/glum/gui/misc/ColorCellRenderer.java
Normal file
@@ -0,0 +1,60 @@
|
||||
package glum.gui.misc;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.table.TableCellRenderer;
|
||||
|
||||
public class ColorCellRenderer extends JPanel implements TableCellRenderer
|
||||
{
|
||||
// State vars
|
||||
protected Color activeColor;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public ColorCellRenderer()
|
||||
{
|
||||
super();
|
||||
|
||||
activeColor = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
|
||||
{
|
||||
activeColor = null;
|
||||
if (value instanceof Color)
|
||||
activeColor = (Color)value;
|
||||
|
||||
if (activeColor != null)
|
||||
setBackground(activeColor);
|
||||
else
|
||||
setBackground(Color.LIGHT_GRAY);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paint(Graphics g)
|
||||
{
|
||||
Graphics2D g2d;
|
||||
|
||||
super.paint(g);
|
||||
g2d = (Graphics2D)g;
|
||||
|
||||
// Bail if we have a valid color
|
||||
if (activeColor != null)
|
||||
return;
|
||||
|
||||
// Draw a red x if no valid color
|
||||
g2d.setColor(Color.RED);
|
||||
g2d.drawLine(0, 0, getWidth(), getHeight());
|
||||
g2d.drawLine(getWidth(), 0, 0, getHeight());
|
||||
}
|
||||
|
||||
}
|
||||
89
src/glum/gui/misc/MultiState.java
Normal file
89
src/glum/gui/misc/MultiState.java
Normal file
@@ -0,0 +1,89 @@
|
||||
package glum.gui.misc;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
public enum MultiState
|
||||
{
|
||||
Checked("Checked", "MultiState.Checked")
|
||||
{
|
||||
@Override
|
||||
public void render(Graphics g, int x, int y, int iconSize)
|
||||
{
|
||||
g.fillRect(x + 3, y + 5, 2, iconSize - 8);
|
||||
g.drawLine(x + (iconSize - 4), y + 3, x + 5, y + (iconSize - 6));
|
||||
g.drawLine(x + (iconSize - 4), y + 4, x + 5, y + (iconSize - 5));
|
||||
}
|
||||
},
|
||||
|
||||
Crossed("Crossed", "MultiState.Crossed")
|
||||
{
|
||||
@Override
|
||||
public void render(Graphics g, int x, int y, int iconSize)
|
||||
{
|
||||
g.drawLine(x + (iconSize - 4), y + 2, x + 3, y + (iconSize - 5));
|
||||
g.drawLine(x + (iconSize - 4), y + 3, x + 3, y + (iconSize - 4));
|
||||
g.drawLine(x + 3, y + 2, x + (iconSize - 4), y + (iconSize - 5));
|
||||
g.drawLine(x + 3, y + 3, x + (iconSize - 4), y + (iconSize - 4));
|
||||
}
|
||||
},
|
||||
|
||||
Mixed("Mixed", "MultiState.Mixed")
|
||||
{
|
||||
@Override
|
||||
public void render(Graphics g, int x, int y, int iconSize)
|
||||
{
|
||||
int cX, cY;
|
||||
|
||||
cX = x + iconSize / 2;
|
||||
cY = y + iconSize / 2;
|
||||
|
||||
g.drawOval(cX - 2, cY - 2, 4, 4);
|
||||
g.drawOval(cX - 3, cY - 3, 6, 6);
|
||||
}
|
||||
},
|
||||
|
||||
None("None", "MultiState.None")
|
||||
{
|
||||
@Override
|
||||
public void render(Graphics g, int x, int y, int iconSize)
|
||||
{
|
||||
; // Nothing to render
|
||||
}
|
||||
};
|
||||
|
||||
// Vars
|
||||
private final String userStr;
|
||||
private final String referenceName;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
MultiState(String aUserStr, String aReferenceName)
|
||||
{
|
||||
userStr = aUserStr;
|
||||
referenceName = aReferenceName;
|
||||
}
|
||||
|
||||
/**
|
||||
* getReferenceName
|
||||
*/
|
||||
public String getReferenceName()
|
||||
{
|
||||
return referenceName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to draw a representative icon of the state
|
||||
*/
|
||||
public void render(Graphics g, int x, int y, int iconSize)
|
||||
{
|
||||
this.render(g, x, y, iconSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return userStr;
|
||||
}
|
||||
|
||||
}
|
||||
197
src/glum/gui/misc/MultiStateCheckBox.java
Normal file
197
src/glum/gui/misc/MultiStateCheckBox.java
Normal file
@@ -0,0 +1,197 @@
|
||||
package glum.gui.misc;
|
||||
|
||||
import java.awt.event.*;
|
||||
import java.util.*;
|
||||
import javax.swing.*;
|
||||
import javax.swing.plaf.*;
|
||||
|
||||
public class MultiStateCheckBox extends JCheckBox implements MouseListener
|
||||
{
|
||||
// State vars
|
||||
protected MultiStateModel model;
|
||||
protected HashMap<Object, MultiState> nextStateMap;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public MultiStateCheckBox(String text, boolean is3StateCycle)
|
||||
{
|
||||
super(text);
|
||||
|
||||
// Set up our replacement icon
|
||||
super.setIcon(new MultiStateIcon());
|
||||
|
||||
// Construct the cycle order of the MultiState checkbox
|
||||
nextStateMap = new HashMap<Object, MultiState>();
|
||||
nextStateMap.put(false, MultiState.Checked);
|
||||
nextStateMap.put(true, MultiState.None);
|
||||
if (is3StateCycle == false)
|
||||
{
|
||||
nextStateMap.put(MultiState.Checked, MultiState.None);
|
||||
nextStateMap.put(MultiState.None, MultiState.Checked);
|
||||
nextStateMap.put(MultiState.Mixed, MultiState.None);
|
||||
}
|
||||
else
|
||||
{
|
||||
nextStateMap.put(MultiState.None, MultiState.Checked);
|
||||
nextStateMap.put(MultiState.Checked, MultiState.Mixed);
|
||||
nextStateMap.put(MultiState.Mixed, MultiState.None);
|
||||
// nextStateMap.put(MultiState.Mixed, MultiState.Crossed);
|
||||
}
|
||||
|
||||
// Register for mouse events
|
||||
super.addMouseListener(this);
|
||||
|
||||
// Reset the keyboard action map
|
||||
rebuildKeyboardMap();
|
||||
|
||||
// set the model to the adapted model
|
||||
model = new MultiStateModel(getModel(), nextStateMap);
|
||||
setModel(model);
|
||||
setState(MultiState.None);
|
||||
}
|
||||
|
||||
public MultiStateCheckBox(String text, HashMap<Object, MultiState> aNextStateMap)
|
||||
{
|
||||
super(text, false);
|
||||
|
||||
// Insanity check
|
||||
if (aNextStateMap == null)
|
||||
throw new NullPointerException();
|
||||
|
||||
// Save off the custom cycle order of the MultiState checkbox
|
||||
nextStateMap = aNextStateMap;
|
||||
}
|
||||
|
||||
public MultiStateCheckBox(String text)
|
||||
{
|
||||
this(text, false);
|
||||
}
|
||||
|
||||
public MultiStateCheckBox()
|
||||
{
|
||||
this(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doClick()
|
||||
{
|
||||
MouseEvent aEvent;
|
||||
|
||||
aEvent = new MouseEvent(this, MouseEvent.MOUSE_PRESSED, 0, 0, 0, 0, 0, false);
|
||||
handleMouseEvent(aEvent);
|
||||
model.advanceToNextState();
|
||||
}
|
||||
|
||||
/** No one may add mouse listeners, not even Swing! */
|
||||
@Override
|
||||
public void addMouseListener(MouseListener l)
|
||||
{
|
||||
}
|
||||
|
||||
/** No one may set a new icon */
|
||||
@Override
|
||||
public void setIcon(Icon icon)
|
||||
{
|
||||
}
|
||||
|
||||
// @formatter:off
|
||||
/**
|
||||
* MouseListener interface methods
|
||||
*/
|
||||
@Override public void mouseClicked(MouseEvent e) { handleMouseEvent(e); }
|
||||
@Override public void mouseEntered(MouseEvent e) { handleMouseEvent(e); }
|
||||
@Override public void mouseExited(MouseEvent e) { handleMouseEvent(e); }
|
||||
@Override public void mousePressed(MouseEvent e) { handleMouseEvent(e); }
|
||||
@Override public void mouseReleased(MouseEvent e) { handleMouseEvent(e); }
|
||||
// @formatter:on
|
||||
|
||||
/**
|
||||
* Return the current state of the Checkbox
|
||||
*/
|
||||
public MultiState getState()
|
||||
{
|
||||
return model.getState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelected(boolean selected)
|
||||
{
|
||||
if (selected)
|
||||
setState(MultiState.Checked);
|
||||
else
|
||||
setState(MultiState.None);
|
||||
}
|
||||
|
||||
/**
|
||||
* setState
|
||||
*/
|
||||
public void setState(MultiState state)
|
||||
{
|
||||
model.setState(state);
|
||||
|
||||
repaint();
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method for handling various MouseEvents
|
||||
*/
|
||||
protected void handleMouseEvent(MouseEvent e)
|
||||
{
|
||||
int aID;
|
||||
|
||||
aID = e.getID();
|
||||
if (aID == MouseEvent.MOUSE_ENTERED)
|
||||
{
|
||||
model.setArmed(true);
|
||||
}
|
||||
else if (aID == MouseEvent.MOUSE_EXITED)
|
||||
{
|
||||
model.setArmed(false);
|
||||
}
|
||||
else if (aID == MouseEvent.MOUSE_RELEASED)
|
||||
{
|
||||
if (model.isArmed() == true)
|
||||
model.advanceToNextState();
|
||||
|
||||
model.setPressed(false);
|
||||
}
|
||||
else if (aID == MouseEvent.MOUSE_PRESSED)
|
||||
{
|
||||
grabFocus();
|
||||
model.setPressed(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to set up a custom keyboard map
|
||||
*/
|
||||
protected void rebuildKeyboardMap()
|
||||
{
|
||||
ActionMap map;
|
||||
|
||||
map = new ActionMapUIResource();
|
||||
|
||||
map.put("pressed", new AbstractAction()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e)
|
||||
{
|
||||
model.setPressed(true);
|
||||
}
|
||||
});
|
||||
|
||||
map.put("released", new AbstractAction()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e)
|
||||
{
|
||||
model.setPressed(false);
|
||||
model.advanceToNextState();
|
||||
}
|
||||
});
|
||||
|
||||
SwingUtilities.replaceUIActionMap(this, map);
|
||||
}
|
||||
|
||||
}
|
||||
68
src/glum/gui/misc/MultiStateCheckBoxCellEditor.java
Normal file
68
src/glum/gui/misc/MultiStateCheckBoxCellEditor.java
Normal file
@@ -0,0 +1,68 @@
|
||||
package glum.gui.misc;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedList;
|
||||
import javax.swing.AbstractCellEditor;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.table.TableCellEditor;
|
||||
|
||||
public class MultiStateCheckBoxCellEditor extends AbstractCellEditor implements ActionListener, TableCellEditor
|
||||
{
|
||||
// State vars
|
||||
protected Collection<ActionListener> myListeners;
|
||||
protected MultiStateCheckBox refMultiStateCheckBox;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public MultiStateCheckBoxCellEditor()
|
||||
{
|
||||
myListeners = new LinkedList<ActionListener>();
|
||||
refMultiStateCheckBox = new MultiStateCheckBox("", false);
|
||||
refMultiStateCheckBox.addActionListener(this);
|
||||
}
|
||||
|
||||
public void addActionListener(ActionListener aListener)
|
||||
{
|
||||
myListeners.add(aListener);
|
||||
}
|
||||
|
||||
public void removeActionListener(ActionListener aListener)
|
||||
{
|
||||
myListeners.remove(aListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent aEvent)
|
||||
{
|
||||
fireEditingStopped();
|
||||
|
||||
aEvent = new ActionEvent(this, aEvent.getID(), "MultiStateCheckBoxCell edited.");
|
||||
for (ActionListener aListener : myListeners)
|
||||
aListener.actionPerformed(aEvent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column)
|
||||
{
|
||||
// Update our checkbox with the appropriate state
|
||||
refMultiStateCheckBox.removeActionListener(this);
|
||||
if (value instanceof MultiState)
|
||||
refMultiStateCheckBox.setState((MultiState)value);
|
||||
else if (value instanceof Boolean)
|
||||
refMultiStateCheckBox.setSelected((Boolean)value);
|
||||
refMultiStateCheckBox.addActionListener(this);
|
||||
|
||||
return refMultiStateCheckBox;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getCellEditorValue()
|
||||
{
|
||||
return refMultiStateCheckBox.getState();
|
||||
}
|
||||
|
||||
}
|
||||
40
src/glum/gui/misc/MultiStateCheckBoxCellRenderer.java
Normal file
40
src/glum/gui/misc/MultiStateCheckBoxCellRenderer.java
Normal file
@@ -0,0 +1,40 @@
|
||||
package glum.gui.misc;
|
||||
|
||||
import java.awt.Component;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.table.TableCellRenderer;
|
||||
|
||||
public class MultiStateCheckBoxCellRenderer extends MultiStateCheckBox implements TableCellRenderer
|
||||
{
|
||||
// State vars
|
||||
protected MultiStateCheckBox refMultiStateCheckBox;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public MultiStateCheckBoxCellRenderer()
|
||||
{
|
||||
refMultiStateCheckBox = new MultiStateCheckBox("", false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
|
||||
{
|
||||
if (value instanceof MultiState)
|
||||
{
|
||||
refMultiStateCheckBox.setState((MultiState)value);
|
||||
return refMultiStateCheckBox;
|
||||
}
|
||||
else if (value instanceof Boolean)
|
||||
{
|
||||
if ((Boolean)value == true)
|
||||
refMultiStateCheckBox.setState(MultiState.Checked);
|
||||
else
|
||||
refMultiStateCheckBox.setState(MultiState.None);
|
||||
return refMultiStateCheckBox;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
174
src/glum/gui/misc/MultiStateCheckBoxHeader.java
Normal file
174
src/glum/gui/misc/MultiStateCheckBoxHeader.java
Normal file
@@ -0,0 +1,174 @@
|
||||
package glum.gui.misc;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import javax.swing.*;
|
||||
import javax.swing.table.*;
|
||||
|
||||
public class MultiStateCheckBoxHeader extends MultiStateCheckBox implements TableCellRenderer, MouseListener, MouseMotionListener
|
||||
{
|
||||
// State vars
|
||||
protected JTableHeader refHeader;
|
||||
protected int column;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public MultiStateCheckBoxHeader(JTable aTable, boolean is3StateCycle)
|
||||
{
|
||||
super("", is3StateCycle);
|
||||
|
||||
// Register for mouse events on the table header
|
||||
refHeader = aTable.getTableHeader();
|
||||
if (refHeader != null)
|
||||
{
|
||||
refHeader.addMouseListener(this);
|
||||
refHeader.addMouseMotionListener(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
System.out.println("Failed to register a mouse listener onto the table header.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the column associated with the mouse event
|
||||
*/
|
||||
public int getAssociatedColumn(MouseEvent aEvent)
|
||||
{
|
||||
JTableHeader aHeader;
|
||||
JTable aTable;
|
||||
TableColumnModel aColumnModel;
|
||||
int viewCol, refCol;
|
||||
|
||||
if (aEvent.getSource() instanceof JTableHeader == false)
|
||||
return -1;
|
||||
|
||||
aHeader = (JTableHeader)aEvent.getSource();
|
||||
aTable = aHeader.getTable();
|
||||
aColumnModel = aTable.getColumnModel();
|
||||
viewCol = aColumnModel.getColumnIndexAtX(aEvent.getX());
|
||||
refCol = aTable.convertColumnIndexToModel(viewCol);
|
||||
|
||||
return viewCol;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int aColumn)
|
||||
{
|
||||
|
||||
if (table != null)
|
||||
{
|
||||
JTableHeader header = table.getTableHeader();
|
||||
if (header != null)
|
||||
{
|
||||
setForeground(header.getForeground());
|
||||
setBackground(header.getBackground());
|
||||
setFont(header.getFont());
|
||||
|
||||
// Perhaps we should deregister our listener and register in case we get a new header
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
column = aColumn;
|
||||
setText((value == null) ? "" : value.toString());
|
||||
setBorder(UIManager.getBorder("TableHeader.cellBorder"));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e)
|
||||
{
|
||||
// Go back to the deactivated state
|
||||
model.setPressed(false);
|
||||
((Component)e.getSource()).repaint();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e)
|
||||
{
|
||||
// Bail if this mouse event does not correspond to our column
|
||||
if (getAssociatedColumn(e) != column)
|
||||
return;
|
||||
|
||||
// Always activate on mouse press
|
||||
model.setPressed(true);
|
||||
((Component)e.getSource()).repaint();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseReleased(MouseEvent e)
|
||||
{
|
||||
// Bail if this mouse event does not correspond to our column
|
||||
if (getAssociatedColumn(e) != column)
|
||||
return;
|
||||
|
||||
// Advance to the next state (if armed)
|
||||
if (model.isArmed() == true)
|
||||
model.advanceToNextState();
|
||||
else
|
||||
model.setArmed(true);
|
||||
|
||||
// Always deactivate on mouse release
|
||||
model.setPressed(false);
|
||||
((Component)e.getSource()).repaint();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseEntered(MouseEvent e)
|
||||
{
|
||||
// Bail if this mouse event does not correspond to our column
|
||||
if (getAssociatedColumn(e) != column)
|
||||
return;
|
||||
|
||||
// Activate our model
|
||||
model.setArmed(true);
|
||||
((Component)e.getSource()).repaint();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseExited(MouseEvent e)
|
||||
{
|
||||
model.setArmed(false);
|
||||
((Component)e.getSource()).repaint();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseMoved(MouseEvent e)
|
||||
{
|
||||
// Deactivate if not in our column
|
||||
if (getAssociatedColumn(e) != column)
|
||||
{
|
||||
model.setArmed(false);
|
||||
model.setPressed(false);
|
||||
}
|
||||
// Activate if we are in our column
|
||||
else
|
||||
{
|
||||
model.setArmed(true);
|
||||
}
|
||||
|
||||
((Component)e.getSource()).repaint();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseDragged(MouseEvent e)
|
||||
{
|
||||
// Always deactivate whenever dragging starts to occur
|
||||
model.setArmed(false);
|
||||
model.setPressed(false);
|
||||
((Component)e.getSource()).repaint();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setState(MultiState aState)
|
||||
{
|
||||
super.setState(aState);
|
||||
|
||||
if (refHeader != null)
|
||||
refHeader.repaint();
|
||||
}
|
||||
|
||||
}
|
||||
83
src/glum/gui/misc/MultiStateCheckBoxHeaderTest.java
Normal file
83
src/glum/gui/misc/MultiStateCheckBoxHeaderTest.java
Normal file
@@ -0,0 +1,83 @@
|
||||
package glum.gui.misc;
|
||||
|
||||
import java.awt.event.*;
|
||||
import java.util.*;
|
||||
import javax.swing.*;
|
||||
import javax.swing.table.*;
|
||||
|
||||
public class MultiStateCheckBoxHeaderTest extends JFrame implements ActionListener
|
||||
{
|
||||
public MultiStateCheckBoxHeaderTest()
|
||||
{
|
||||
super("MultiStateCheckBoxHeaderTest");
|
||||
|
||||
buildGui();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Test application entry point
|
||||
*/
|
||||
public static void main(String[] argv)
|
||||
{
|
||||
MultiStateCheckBoxHeaderTest mainClass;
|
||||
|
||||
mainClass = new MultiStateCheckBoxHeaderTest();
|
||||
|
||||
mainClass.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
mainClass.setVisible(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e)
|
||||
{
|
||||
Object source;
|
||||
String text;
|
||||
|
||||
source = e.getSource();
|
||||
text = "";
|
||||
if (source instanceof AbstractButton)
|
||||
text = ((AbstractButton)source).getText();
|
||||
|
||||
System.out.println("HeaderListener::actionPerformed() " + text + ", state:" + ((MultiStateCheckBoxHeader)source).getState());
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to build the main GUI
|
||||
*/
|
||||
private void buildGui()
|
||||
{
|
||||
JTable table;
|
||||
DefaultTableModel dataModel;
|
||||
JScrollPane scrollpane;
|
||||
MultiStateCheckBoxHeader aHeader;
|
||||
|
||||
// Create sample content for the JTable, don't care
|
||||
String[][] data = new String[7][5];
|
||||
String[] headers = new String[5];
|
||||
for (int col = 0; col < data[0].length; col++)
|
||||
{
|
||||
headers[col] = "- " + col + " -";
|
||||
for (int row = 0; row < data.length; row++)
|
||||
data[row][col] = "(" + row + "," + col + ")";
|
||||
}
|
||||
dataModel = new DefaultTableModel(data, headers);
|
||||
table = new JTable(dataModel);
|
||||
|
||||
// Create a HeaderCellRenderer for each column
|
||||
Enumeration<TableColumn> enumeration = table.getColumnModel().getColumns();
|
||||
while (enumeration.hasMoreElements())
|
||||
{
|
||||
TableColumn aColumn = enumeration.nextElement();
|
||||
aHeader = new MultiStateCheckBoxHeader(table, true);
|
||||
aHeader.addActionListener(this);
|
||||
aColumn.setHeaderRenderer(aHeader);
|
||||
}
|
||||
|
||||
scrollpane = new JScrollPane(table);
|
||||
getContentPane().add(scrollpane);
|
||||
|
||||
pack();
|
||||
}
|
||||
|
||||
}
|
||||
34
src/glum/gui/misc/MultiStateCheckBoxTest.java
Normal file
34
src/glum/gui/misc/MultiStateCheckBoxTest.java
Normal file
@@ -0,0 +1,34 @@
|
||||
package glum.gui.misc;
|
||||
|
||||
import java.awt.*;
|
||||
import javax.swing.*;
|
||||
|
||||
public class MultiStateCheckBoxTest
|
||||
{
|
||||
public static void main(String args[]) throws Exception
|
||||
{
|
||||
JFrame frame;
|
||||
JCheckBox multi1CB, multi2CB;
|
||||
JCheckBox standardCB;
|
||||
|
||||
frame = new JFrame("MultiStateCheckBoxTest");
|
||||
frame.getContentPane().setLayout(new GridLayout(0, 1, 5, 5));
|
||||
|
||||
standardCB = new JCheckBox("Standard checkbox");
|
||||
standardCB.setMnemonic('S');
|
||||
frame.getContentPane().add(standardCB);
|
||||
|
||||
multi1CB = new MultiStateCheckBox("Multistate-1 checkbox", false);
|
||||
multi1CB.setMnemonic('1');
|
||||
frame.getContentPane().add(multi1CB);
|
||||
|
||||
multi2CB = new MultiStateCheckBox("Multistate-2 checkbox", true);
|
||||
multi2CB.setMnemonic('2');
|
||||
frame.getContentPane().add(multi2CB);
|
||||
|
||||
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
frame.pack();
|
||||
frame.setVisible(true);
|
||||
}
|
||||
|
||||
}
|
||||
114
src/glum/gui/misc/MultiStateIcon.java
Normal file
114
src/glum/gui/misc/MultiStateIcon.java
Normal file
@@ -0,0 +1,114 @@
|
||||
package glum.gui.misc;
|
||||
|
||||
import java.awt.*;
|
||||
import javax.swing.*;
|
||||
import javax.swing.plaf.metal.*;
|
||||
|
||||
public class MultiStateIcon implements Icon
|
||||
{
|
||||
@Override
|
||||
public int getIconWidth()
|
||||
{
|
||||
return getIconSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIconHeight()
|
||||
{
|
||||
return getIconSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintIcon(Component c, Graphics g, int x, int y)
|
||||
{
|
||||
MultiStateModel model;
|
||||
MultiState aState;
|
||||
int iconSize;
|
||||
|
||||
// Insanity check
|
||||
if (c instanceof MultiStateCheckBox == false)
|
||||
return;
|
||||
|
||||
model = (MultiStateModel)((JCheckBox)c).getModel();
|
||||
iconSize = getIconSize();
|
||||
|
||||
if (model.isEnabled())
|
||||
{
|
||||
if (model.isPressed() && model.isArmed())
|
||||
{
|
||||
g.setColor(MetalLookAndFeel.getControlShadow());
|
||||
g.fillRect(x, y, iconSize - 1, iconSize - 1);
|
||||
drawPressed3DBorder(g, x, y, iconSize, iconSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (model.isArmed() == true)
|
||||
{
|
||||
g.setColor(MetalLookAndFeel.getControlShadow());
|
||||
drawPressed3DBorder(g, x, y, iconSize, iconSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
drawFlush3DBorder(g, x, y, iconSize, iconSize);
|
||||
}
|
||||
}
|
||||
|
||||
g.setColor(MetalLookAndFeel.getControlInfo());
|
||||
}
|
||||
else
|
||||
{
|
||||
g.setColor(MetalLookAndFeel.getControlShadow());
|
||||
g.drawRect(x, y, iconSize - 1, iconSize - 1);
|
||||
}
|
||||
|
||||
// Render the appropriate symbol
|
||||
aState = model.getState();
|
||||
aState.render(g, x, y, iconSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method
|
||||
*/
|
||||
protected void drawFlush3DBorder(Graphics g, int x, int y, int w, int h)
|
||||
{
|
||||
g.translate(x, y);
|
||||
g.setColor(MetalLookAndFeel.getControlDarkShadow());
|
||||
g.drawRect(0, 0, w - 2, h - 2);
|
||||
g.setColor(MetalLookAndFeel.getControlHighlight());
|
||||
g.drawRect(1, 1, w - 2, h - 2);
|
||||
g.setColor(MetalLookAndFeel.getControl());
|
||||
g.drawLine(0, h - 1, 1, h - 2);
|
||||
g.drawLine(w - 1, 0, w - 2, 1);
|
||||
g.translate(-x, -y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method
|
||||
*/
|
||||
protected void drawPressed3DBorder(Graphics g, int x, int y, int w, int h)
|
||||
{
|
||||
g.translate(x, y);
|
||||
drawFlush3DBorder(g, 0, 0, w, h);
|
||||
g.setColor(MetalLookAndFeel.getControlShadow());
|
||||
g.drawLine(1, 1, 1, h - 2);
|
||||
g.drawLine(1, 1, w - 2, 1);
|
||||
g.drawLine(2, 1, 2, h - 2);
|
||||
g.drawLine(1, 2, w - 2, 2);
|
||||
|
||||
g.drawLine(w - 2, 1, w - 2, h - 2);
|
||||
g.drawLine(1, h - 2, w - 2, h - 2);
|
||||
g.drawLine(w - 3, 1, w - 3, h - 2);
|
||||
g.drawLine(1, h - 3, w - 2, h - 3);
|
||||
|
||||
g.translate(-x, -y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the square dimensions of this GUI
|
||||
*/
|
||||
protected int getIconSize()
|
||||
{
|
||||
return 13;
|
||||
}
|
||||
|
||||
}
|
||||
181
src/glum/gui/misc/MultiStateModel.java
Normal file
181
src/glum/gui/misc/MultiStateModel.java
Normal file
@@ -0,0 +1,181 @@
|
||||
package glum.gui.misc;
|
||||
|
||||
import java.awt.event.*;
|
||||
import java.util.*;
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.*;
|
||||
|
||||
public class MultiStateModel implements ButtonModel
|
||||
{
|
||||
protected final ButtonModel refModel;
|
||||
protected final HashMap<Object, MultiState> nextStateMap;
|
||||
protected MultiState myState;
|
||||
|
||||
public MultiStateModel(ButtonModel aRefModel, HashMap<Object, MultiState> aNextStateMap)
|
||||
{
|
||||
refModel = aRefModel;
|
||||
nextStateMap = aNextStateMap;
|
||||
|
||||
myState = MultiState.None;
|
||||
}
|
||||
|
||||
public void advanceToNextState()
|
||||
{
|
||||
MultiState aState;
|
||||
|
||||
aState = nextStateMap.get(myState);
|
||||
if (aState == null)
|
||||
aState = MultiState.None;
|
||||
|
||||
setState(aState);
|
||||
}
|
||||
|
||||
public MultiState getState()
|
||||
{
|
||||
return myState;
|
||||
}
|
||||
|
||||
public void setState(MultiState state)
|
||||
{
|
||||
this.myState = state;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSelected()
|
||||
{
|
||||
if (myState != MultiState.None)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* All these methods simply delegate to the "refModel" model that is being decorated.
|
||||
*/
|
||||
@Override
|
||||
public boolean isArmed()
|
||||
{
|
||||
return refModel.isArmed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled()
|
||||
{
|
||||
return refModel.isEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPressed()
|
||||
{
|
||||
return refModel.isPressed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRollover()
|
||||
{
|
||||
return refModel.isRollover();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setArmed(boolean b)
|
||||
{
|
||||
refModel.setArmed(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnabled(boolean b)
|
||||
{
|
||||
refModel.setEnabled(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelected(boolean b)
|
||||
{
|
||||
refModel.setSelected(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPressed(boolean b)
|
||||
{
|
||||
refModel.setPressed(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRollover(boolean b)
|
||||
{
|
||||
refModel.setRollover(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMnemonic(int key)
|
||||
{
|
||||
refModel.setMnemonic(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMnemonic()
|
||||
{
|
||||
return refModel.getMnemonic();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setActionCommand(String s)
|
||||
{
|
||||
refModel.setActionCommand(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getActionCommand()
|
||||
{
|
||||
return refModel.getActionCommand();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGroup(ButtonGroup group)
|
||||
{
|
||||
refModel.setGroup(group);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addActionListener(ActionListener l)
|
||||
{
|
||||
refModel.addActionListener(l);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeActionListener(ActionListener l)
|
||||
{
|
||||
refModel.removeActionListener(l);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addItemListener(ItemListener l)
|
||||
{
|
||||
refModel.addItemListener(l);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeItemListener(ItemListener l)
|
||||
{
|
||||
refModel.removeItemListener(l);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addChangeListener(ChangeListener l)
|
||||
{
|
||||
refModel.addChangeListener(l);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeChangeListener(ChangeListener l)
|
||||
{
|
||||
refModel.removeChangeListener(l);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] getSelectedObjects()
|
||||
{
|
||||
return refModel.getSelectedObjects();
|
||||
}
|
||||
|
||||
}
|
||||
60
src/glum/gui/misc/SimpleTitledBorder.java
Normal file
60
src/glum/gui/misc/SimpleTitledBorder.java
Normal file
@@ -0,0 +1,60 @@
|
||||
package glum.gui.misc;
|
||||
|
||||
import java.awt.*;
|
||||
import javax.swing.*;
|
||||
import javax.swing.text.*;
|
||||
import javax.swing.border.*;
|
||||
|
||||
public class SimpleTitledBorder extends TitledBorder
|
||||
{
|
||||
// Class var used to strip the disabled color
|
||||
private static JTextComponent testComponent = null;
|
||||
|
||||
/**
|
||||
* Constuctor
|
||||
*/
|
||||
public SimpleTitledBorder(Border border)
|
||||
{
|
||||
super(border);
|
||||
}
|
||||
|
||||
public SimpleTitledBorder(Border border, String title)
|
||||
{
|
||||
super(border, title);
|
||||
}
|
||||
|
||||
public SimpleTitledBorder(Border border, String title, int titleJustification, int titlePosition)
|
||||
{
|
||||
super(border, title, titleJustification, titlePosition);
|
||||
}
|
||||
|
||||
public SimpleTitledBorder(Border border, String title, int titleJustification, int titlePosition, Font titleFont)
|
||||
{
|
||||
super(border, title, titleJustification, titlePosition, titleFont);
|
||||
}
|
||||
|
||||
public SimpleTitledBorder(Border border, String title, int titleJustification, int titlePosition, Font titleFont, Color titleColor)
|
||||
{
|
||||
super(border, title, titleJustification, titlePosition, titleFont, titleColor);
|
||||
}
|
||||
|
||||
public SimpleTitledBorder(String title)
|
||||
{
|
||||
super(title);
|
||||
}
|
||||
|
||||
/**
|
||||
* setEnabled
|
||||
*/
|
||||
public void setEnabled(boolean aBool)
|
||||
{
|
||||
if (testComponent == null)
|
||||
testComponent = new JTextField();
|
||||
|
||||
// ! TODO: Color should be based on system settings
|
||||
setTitleColor(Color.BLACK);
|
||||
if (aBool == false)
|
||||
setTitleColor(testComponent.getDisabledTextColor());
|
||||
}
|
||||
|
||||
}
|
||||
89
src/glum/gui/panel/CardPanel.java
Normal file
89
src/glum/gui/panel/CardPanel.java
Normal file
@@ -0,0 +1,89 @@
|
||||
package glum.gui.panel;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.*;
|
||||
import javax.swing.*;
|
||||
|
||||
import com.google.common.collect.*;
|
||||
|
||||
public class CardPanel<G1> extends JPanel
|
||||
{
|
||||
protected BiMap<String, G1> myMap;
|
||||
protected CardLayout myLayout;
|
||||
protected G1 activeCard;
|
||||
|
||||
public CardPanel()
|
||||
{
|
||||
super();
|
||||
|
||||
myLayout = new CardLayout();
|
||||
setLayout(myLayout);
|
||||
|
||||
myMap = HashBiMap.create();
|
||||
activeCard = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component add(String name, Component comp)
|
||||
{
|
||||
throw new RuntimeException("Improper method call. Use addCard() instead of add()");
|
||||
}
|
||||
|
||||
public void addCard(String aTitle, G1 aComponent)
|
||||
{
|
||||
// aComponent must be of type Component
|
||||
if ((aComponent instanceof Component) == false)
|
||||
throw new IllegalArgumentException("aComponent must be of type Component. Found class: " + aComponent.getClass().getName());
|
||||
|
||||
// Add the component if no component associated with the key
|
||||
if (myMap.get(aTitle) == null)
|
||||
{
|
||||
myMap.put(aTitle, aComponent);
|
||||
add((Component)aComponent, aTitle);
|
||||
}
|
||||
// If the key is associated, then ensure it is matched to aComponent
|
||||
else if (myMap.get(aTitle) != aComponent)
|
||||
{
|
||||
throw new RuntimeException("Attempting to add new card with an already inserted key: " + aTitle);
|
||||
}
|
||||
|
||||
switchToCard(aTitle);
|
||||
}
|
||||
|
||||
public G1 getActiveCard()
|
||||
{
|
||||
return activeCard;
|
||||
}
|
||||
|
||||
public Collection<G1> getAllCards()
|
||||
{
|
||||
Collection<G1> itemList;
|
||||
|
||||
itemList = new ArrayList<G1>(myMap.values());
|
||||
return itemList;
|
||||
}
|
||||
|
||||
public Set<String> getCardNames()
|
||||
{
|
||||
return new HashSet<String>(myMap.keySet());
|
||||
}
|
||||
|
||||
public void switchToCard(String aTitle)
|
||||
{
|
||||
activeCard = myMap.get(aTitle);
|
||||
if (activeCard == null)
|
||||
throw new RuntimeException("No mapping found when switching to card: " + aTitle);
|
||||
|
||||
myLayout.show(this, aTitle);
|
||||
}
|
||||
|
||||
public void switchToCard(G1 aCard)
|
||||
{
|
||||
if (myMap.values().contains(aCard) == false)
|
||||
throw new RuntimeException("No mapping found when switching to card: " + aCard);
|
||||
|
||||
activeCard = aCard;
|
||||
myLayout.show(this, myMap.inverse().get(aCard));
|
||||
}
|
||||
|
||||
}
|
||||
367
src/glum/gui/panel/ColorInputPanel.java
Normal file
367
src/glum/gui/panel/ColorInputPanel.java
Normal file
@@ -0,0 +1,367 @@
|
||||
package glum.gui.panel;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.util.*;
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.*;
|
||||
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
import glum.gui.component.GNumberField;
|
||||
import glum.unit.ConstUnitProvider;
|
||||
import glum.unit.NumberUnit;
|
||||
import glum.unit.UnitProvider;
|
||||
|
||||
public class ColorInputPanel extends JPanel implements ActionListener, ChangeListener
|
||||
{
|
||||
// Constants
|
||||
private static final Font miniFont = new Font("Serif", Font.PLAIN, 10);
|
||||
|
||||
// Gui components
|
||||
private ColorPanel colorP;
|
||||
private JLabel redL, greenL, blueL;
|
||||
private JSlider redS, greenS, blueS;
|
||||
private GNumberField redNF, greenNF, blueNF;
|
||||
|
||||
// State vars
|
||||
private Collection<ActionListener> myActionListeners;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public ColorInputPanel(boolean isHorizontal, boolean showTF)
|
||||
{
|
||||
super();
|
||||
|
||||
// Init internal vars
|
||||
myActionListeners = new LinkedHashSet<ActionListener>();
|
||||
|
||||
// Build the gui areas
|
||||
buildGuiArea(isHorizontal, showTF);
|
||||
|
||||
// Set in the default color
|
||||
setColor(Color.BLACK);
|
||||
}
|
||||
|
||||
/**
|
||||
* addActionListener
|
||||
*/
|
||||
public synchronized void addActionListener(ActionListener aActionListener)
|
||||
{
|
||||
// Insanity check
|
||||
if (aActionListener == null)
|
||||
return;
|
||||
|
||||
myActionListeners.add(aActionListener);
|
||||
}
|
||||
|
||||
/**
|
||||
* removeActionListener
|
||||
*/
|
||||
public synchronized void removeActionListener(ActionListener aActionListener)
|
||||
{
|
||||
// Insanity check
|
||||
if (aActionListener == null)
|
||||
return;
|
||||
|
||||
myActionListeners.remove(aActionListener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the selected color
|
||||
*/
|
||||
public Color getColor()
|
||||
{
|
||||
int redVal, greenVal, blueVal;
|
||||
|
||||
redVal = redS.getValue();
|
||||
greenVal = greenS.getValue();
|
||||
blueVal = blueS.getValue();
|
||||
return new Color(redVal, greenVal, blueVal);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets in the current selected color
|
||||
*/
|
||||
public void setColor(Color aColor)
|
||||
{
|
||||
// Insanity check
|
||||
if (aColor == null)
|
||||
return;
|
||||
|
||||
synchronizeGui(aColor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent aEvent)
|
||||
{
|
||||
Object source;
|
||||
|
||||
// Perform GUI updates
|
||||
source = aEvent.getSource();
|
||||
updateGui(source);
|
||||
|
||||
// Notify the listeners
|
||||
fireActionEvent(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnabled(boolean aBool)
|
||||
{
|
||||
redL.setEnabled(aBool);
|
||||
redS.setEnabled(aBool);
|
||||
redNF.setEnabled(aBool);
|
||||
greenL.setEnabled(aBool);
|
||||
greenS.setEnabled(aBool);
|
||||
greenNF.setEnabled(aBool);
|
||||
blueL.setEnabled(aBool);
|
||||
blueS.setEnabled(aBool);
|
||||
blueNF.setEnabled(aBool);
|
||||
|
||||
colorP.setEnabled(aBool);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stateChanged(ChangeEvent aEvent)
|
||||
{
|
||||
Object source;
|
||||
JSlider aSlider;
|
||||
|
||||
// Perform GUI updates
|
||||
source = aEvent.getSource();
|
||||
updateGui(source);
|
||||
|
||||
// Notify the listeners
|
||||
if (source instanceof JSlider)
|
||||
{
|
||||
// Fire off an event only if not being updated
|
||||
aSlider = (JSlider)source;
|
||||
if (aSlider.getValueIsAdjusting() == false)
|
||||
fireActionEvent(false);
|
||||
else
|
||||
fireActionEvent(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Forms the actual gui
|
||||
*/
|
||||
private void buildGuiArea(boolean isHorizontal, boolean showTF)
|
||||
{
|
||||
JPanel rPanel, gPanel, bPanel;
|
||||
UnitProvider countUP;
|
||||
int sliderStyle;
|
||||
|
||||
sliderStyle = JSlider.HORIZONTAL;
|
||||
if (isHorizontal == false)
|
||||
sliderStyle = JSlider.VERTICAL;
|
||||
|
||||
countUP = new ConstUnitProvider(new NumberUnit("", "", 1.0, 0));
|
||||
|
||||
// RGB sliders
|
||||
redL = new JLabel("R", JLabel.CENTER);
|
||||
redS = new JSlider(sliderStyle, 0, 255, 0);
|
||||
redNF = new GNumberField(this, countUP, 0, 255);
|
||||
rPanel = formColorControl(redS, redL, redNF, isHorizontal, showTF);
|
||||
|
||||
greenL = new JLabel("G", JLabel.CENTER);
|
||||
greenS = new JSlider(sliderStyle, 0, 255, 0);
|
||||
greenNF = new GNumberField(this, countUP, 0, 255);
|
||||
gPanel = formColorControl(greenS, greenL, greenNF, isHorizontal, showTF);
|
||||
|
||||
blueL = new JLabel("B", JLabel.CENTER);
|
||||
blueS = new JSlider(sliderStyle, 0, 255, 0);
|
||||
blueNF = new GNumberField(this, countUP, 0, 255);
|
||||
bPanel = formColorControl(blueS, blueL, blueNF, isHorizontal, showTF);
|
||||
|
||||
// The color area
|
||||
colorP = new ColorPanel(40, 40);
|
||||
|
||||
if (isHorizontal == true)
|
||||
{
|
||||
setLayout(new MigLayout("", "0[grow,75::][]0", "0[][][]0"));
|
||||
|
||||
add(rPanel, "growx,span 1,wrap");
|
||||
add(gPanel, "growx,span 1,wrap");
|
||||
add(bPanel, "growx,span 1,wrap");
|
||||
add(colorP, "cell 1 0,growy,spanx 1,spany 3");
|
||||
}
|
||||
else
|
||||
{
|
||||
setLayout(new MigLayout("", "0[][][]0", "0[grow,75::][]0"));
|
||||
|
||||
add(rPanel, "growy,span 1");
|
||||
add(gPanel, "growy,span 1");
|
||||
add(bPanel, "growy,span 1,wrap");
|
||||
add(colorP, "growx,span 3");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* builds a JSlider with a label
|
||||
*/
|
||||
private JPanel formColorControl(JSlider aS, JLabel aL, GNumberField aNF, boolean isHorizontal, boolean showTF)
|
||||
{
|
||||
JPanel aPanel;
|
||||
|
||||
aPanel = new JPanel();
|
||||
if (isHorizontal == true)
|
||||
{
|
||||
aPanel.setLayout(new BoxLayout(aPanel, BoxLayout.X_AXIS));
|
||||
aL.setAlignmentY(0.5f);
|
||||
aS.setAlignmentY(0.5f);
|
||||
aNF.setAlignmentY(0.5f);
|
||||
}
|
||||
else
|
||||
{
|
||||
aPanel.setLayout(new BoxLayout(aPanel, BoxLayout.Y_AXIS));
|
||||
aL.setAlignmentX(0.5f);
|
||||
aS.setAlignmentX(0.5f);
|
||||
aNF.setAlignmentX(0.5f);
|
||||
}
|
||||
|
||||
aS.addChangeListener(this);
|
||||
|
||||
aNF.setHorizontalAlignment(JTextField.CENTER);
|
||||
aNF.setColumns(3);
|
||||
aNF.setValue(0);
|
||||
aNF.setFont(miniFont);
|
||||
aNF.setMinimumSize(aNF.getPreferredSize());
|
||||
aNF.setMaximumSize(aNF.getPreferredSize());
|
||||
|
||||
aPanel.add(aL);
|
||||
aPanel.add(aS);
|
||||
|
||||
if (isHorizontal == true)
|
||||
aPanel.add(Box.createHorizontalStrut(2));
|
||||
else
|
||||
aPanel.add(Box.createVerticalStrut(2));
|
||||
|
||||
if (showTF == true)
|
||||
aPanel.add(aNF);
|
||||
|
||||
return aPanel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies all listeners of color change
|
||||
*/
|
||||
private void fireActionEvent(boolean isChanging)
|
||||
{
|
||||
Collection<ActionListener> currListeners;
|
||||
ActionEvent aEvent;
|
||||
|
||||
// Get a copy of the current set of listeners
|
||||
synchronized(this)
|
||||
{
|
||||
currListeners = new LinkedHashSet<ActionListener>(myActionListeners);
|
||||
}
|
||||
|
||||
// Construct the event
|
||||
if (isChanging == false)
|
||||
aEvent = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "Color changed.");
|
||||
else
|
||||
aEvent = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "Color changing.");
|
||||
|
||||
// Notify our listeners
|
||||
for (ActionListener aListener : currListeners)
|
||||
{
|
||||
aListener.actionPerformed(aEvent);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Syncs the GUI to match aColor
|
||||
*/
|
||||
private void synchronizeGui(Color aColor)
|
||||
{
|
||||
int redVal, greenVal, blueVal;
|
||||
|
||||
// Get the rgb values
|
||||
redVal = aColor.getRed();
|
||||
greenVal = aColor.getGreen();
|
||||
blueVal = aColor.getBlue();
|
||||
|
||||
// Stop listening to events while updating
|
||||
redS.removeChangeListener(this);
|
||||
greenS.removeChangeListener(this);
|
||||
blueS.removeChangeListener(this);
|
||||
|
||||
// Update the gui components
|
||||
if (redVal != redNF.getValue())
|
||||
redNF.setValue(redVal);
|
||||
if (greenVal != greenNF.getValue())
|
||||
greenNF.setValue(greenVal);
|
||||
if (blueVal != blueNF.getValue())
|
||||
blueNF.setValue(blueVal);
|
||||
redS.setValue(redVal);
|
||||
greenS.setValue(greenVal);
|
||||
blueS.setValue(blueVal);
|
||||
colorP.setColor(new Color(redVal, greenVal, blueVal));
|
||||
|
||||
// Proceed with listening to events
|
||||
redS.addChangeListener(this);
|
||||
greenS.addChangeListener(this);
|
||||
blueS.addChangeListener(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the gui to reflect the source that has changed
|
||||
*/
|
||||
private void updateGui(Object source)
|
||||
{
|
||||
int redVal, greenVal, blueVal;
|
||||
|
||||
// Determine what values to retrieve based on the source
|
||||
if (source instanceof GNumberField)
|
||||
{
|
||||
redVal = redNF.getValueAsInt(0);
|
||||
greenVal = greenNF.getValueAsInt(0);
|
||||
blueVal = blueNF.getValueAsInt(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get the slider values
|
||||
redVal = redS.getValue();
|
||||
greenVal = greenS.getValue();
|
||||
blueVal = blueS.getValue();
|
||||
}
|
||||
|
||||
// Update the appropriate component
|
||||
if (source == redS)
|
||||
{
|
||||
redNF.setValue(redVal);
|
||||
}
|
||||
else if (source == greenS)
|
||||
{
|
||||
greenNF.setValue(greenVal);
|
||||
}
|
||||
else if (source == blueS)
|
||||
{
|
||||
blueNF.setValue(blueVal);
|
||||
}
|
||||
else if (source == redNF)
|
||||
{
|
||||
redS.removeChangeListener(this);
|
||||
redS.setValue(redVal);
|
||||
redS.addChangeListener(this);
|
||||
}
|
||||
else if (source == greenNF)
|
||||
{
|
||||
greenS.removeChangeListener(this);
|
||||
greenS.setValue(greenVal);
|
||||
greenS.addChangeListener(this);
|
||||
}
|
||||
else if (source == blueNF)
|
||||
{
|
||||
blueS.removeChangeListener(this);
|
||||
blueS.setValue(blueVal);
|
||||
blueS.addChangeListener(this);
|
||||
}
|
||||
|
||||
// Update the preview color
|
||||
colorP.setColor(new Color(redVal, greenVal, blueVal));
|
||||
}
|
||||
|
||||
}
|
||||
66
src/glum/gui/panel/ColorPanel.java
Normal file
66
src/glum/gui/panel/ColorPanel.java
Normal file
@@ -0,0 +1,66 @@
|
||||
package glum.gui.panel;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.border.BevelBorder;
|
||||
import javax.swing.border.LineBorder;
|
||||
|
||||
public class ColorPanel extends JPanel
|
||||
{
|
||||
// State vars
|
||||
protected Color dispColor;
|
||||
|
||||
public ColorPanel()
|
||||
{
|
||||
super();
|
||||
|
||||
dispColor = Color.BLACK;
|
||||
updateGui();
|
||||
}
|
||||
|
||||
public ColorPanel(int sizeX, int sizeY)
|
||||
{
|
||||
this();
|
||||
|
||||
setMinimumSize(new Dimension(sizeX, sizeY));
|
||||
setPreferredSize(new Dimension(sizeX, sizeY));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets in the color that is displayed by this component
|
||||
*/
|
||||
public void setColor(Color aColor)
|
||||
{
|
||||
dispColor = aColor;
|
||||
updateGui();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnabled(boolean aBool)
|
||||
{
|
||||
super.setEnabled(aBool);
|
||||
updateGui();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the GUI to reflect the chosen color
|
||||
*/
|
||||
protected void updateGui()
|
||||
{
|
||||
boolean isEnabled;
|
||||
|
||||
isEnabled = isEnabled();
|
||||
if (isEnabled == false)
|
||||
{
|
||||
setBackground(Color.LIGHT_GRAY);
|
||||
setBorder(new LineBorder(Color.GRAY));
|
||||
return;
|
||||
}
|
||||
|
||||
setBackground(dispColor);
|
||||
setBorder(new BevelBorder(BevelBorder.RAISED));
|
||||
}
|
||||
|
||||
}
|
||||
156
src/glum/gui/panel/ComponentTracker.java
Normal file
156
src/glum/gui/panel/ComponentTracker.java
Normal file
@@ -0,0 +1,156 @@
|
||||
package glum.gui.panel;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.event.ComponentEvent;
|
||||
import java.awt.event.ComponentListener;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
/**
|
||||
* Utility class to allow a component to track other Component so it can keep it's
|
||||
* properties synchronized with the tracked Components.
|
||||
*/
|
||||
public class ComponentTracker implements ComponentListener
|
||||
{
|
||||
protected Component targComp;
|
||||
protected Component trkHiddenComp;
|
||||
protected Component trkMovedComp;
|
||||
protected Component trkResizedComp;
|
||||
protected Component trkShownComp;
|
||||
|
||||
public ComponentTracker(Component aTargComp)
|
||||
{
|
||||
targComp = aTargComp;
|
||||
trkHiddenComp = null;
|
||||
trkMovedComp = null;
|
||||
trkResizedComp = null;
|
||||
trkShownComp = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Track aComp so that if it is hidden, then the reference
|
||||
* targetComponent will be hidden.
|
||||
*/
|
||||
public void setHiddenTracker(Component aComp)
|
||||
{
|
||||
// Deregister from the old trkShownComp
|
||||
if (trkHiddenComp != null)
|
||||
trkHiddenComp.removeComponentListener(this);
|
||||
|
||||
trkHiddenComp = aComp;
|
||||
updateListenersForTrackedComponents();
|
||||
}
|
||||
|
||||
/**
|
||||
* Track aComp so that if it is moved, then the reference
|
||||
* targetComponent will be moved.
|
||||
*/
|
||||
public void setMovedTracker(Component aComp)
|
||||
{
|
||||
// Deregister from the old trkShownComp
|
||||
if (trkMovedComp != null)
|
||||
trkMovedComp.removeComponentListener(this);
|
||||
|
||||
trkMovedComp = aComp;
|
||||
updateListenersForTrackedComponents();
|
||||
}
|
||||
|
||||
/**
|
||||
* Track aComp so that if it is resized, then the reference
|
||||
* targetComponent will be resized.
|
||||
*/
|
||||
public void setResizedTracker(Component aComp)
|
||||
{
|
||||
// Deregister from the old trkShownComp
|
||||
if (trkResizedComp != null)
|
||||
trkResizedComp.removeComponentListener(this);
|
||||
|
||||
trkResizedComp = aComp;
|
||||
updateListenersForTrackedComponents();
|
||||
}
|
||||
|
||||
/**
|
||||
* Track aComp so that if it is shown, then the reference
|
||||
* targetComponent will be shown.
|
||||
*/
|
||||
public void setShownTracker(Component aComp)
|
||||
{
|
||||
// Deregister from the old trkShownComp
|
||||
if (trkShownComp != null)
|
||||
trkShownComp.removeComponentListener(this);
|
||||
|
||||
trkShownComp = aComp;
|
||||
updateListenersForTrackedComponents();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void componentHidden(ComponentEvent aEvent)
|
||||
{
|
||||
if (aEvent.getComponent() == trkHiddenComp)
|
||||
targComp.setVisible(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void componentMoved(ComponentEvent aEvent)
|
||||
{
|
||||
if (aEvent.getComponent() == trkMovedComp)
|
||||
targComp.setLocation(trkMovedComp.getLocation());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void componentResized(ComponentEvent aEvent)
|
||||
{
|
||||
if (aEvent.getComponent() == trkResizedComp)
|
||||
{
|
||||
targComp.setSize(trkResizedComp.getSize());
|
||||
targComp.validate();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void componentShown(ComponentEvent aEvent)
|
||||
{
|
||||
if (aEvent.getComponent() == trkShownComp)
|
||||
targComp.setVisible(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to ensure that we are registered (Component events) for
|
||||
* all component which are being tracked. Note that at most we will register
|
||||
* only only once for each unique Component.
|
||||
*/
|
||||
protected void updateListenersForTrackedComponents()
|
||||
{
|
||||
List<ComponentListener> listenerList;
|
||||
|
||||
if (trkHiddenComp != null)
|
||||
{
|
||||
listenerList = Lists.newArrayList(trkHiddenComp.getComponentListeners());
|
||||
if (listenerList.contains(this) == false)
|
||||
trkHiddenComp.addComponentListener(this);
|
||||
}
|
||||
|
||||
if (trkMovedComp != null)
|
||||
{
|
||||
listenerList = Lists.newArrayList(trkMovedComp.getComponentListeners());
|
||||
if (listenerList.contains(this) == false)
|
||||
trkMovedComp.addComponentListener(this);
|
||||
}
|
||||
|
||||
if (trkResizedComp != null)
|
||||
{
|
||||
listenerList = Lists.newArrayList(trkResizedComp.getComponentListeners());
|
||||
if (listenerList.contains(this) == false)
|
||||
trkResizedComp.addComponentListener(this);
|
||||
}
|
||||
|
||||
if (trkShownComp != null)
|
||||
{
|
||||
listenerList = Lists.newArrayList(trkShownComp.getComponentListeners());
|
||||
if (listenerList.contains(this) == false)
|
||||
trkShownComp.addComponentListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
289
src/glum/gui/panel/CredentialPanel.java
Normal file
289
src/glum/gui/panel/CredentialPanel.java
Normal file
@@ -0,0 +1,289 @@
|
||||
package glum.gui.panel;
|
||||
|
||||
import glum.net.Credential;
|
||||
import glum.net.NetUtil;
|
||||
import glum.net.Result;
|
||||
import glum.gui.FocusUtil;
|
||||
import glum.gui.GuiUtil;
|
||||
import glum.gui.action.ClickAction;
|
||||
import glum.gui.component.GPasswordField;
|
||||
import glum.gui.component.GTextField;
|
||||
import glum.gui.panel.GlassPanel;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPasswordField;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.border.BevelBorder;
|
||||
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
public class CredentialPanel extends GlassPanel implements ActionListener
|
||||
{
|
||||
// Constants
|
||||
private static final Color warnColor = new Color(128, 0, 0);
|
||||
|
||||
// GUI vars
|
||||
protected JLabel titleL;
|
||||
protected JButton ignoreB, acceptB;
|
||||
protected JPasswordField passTF;
|
||||
protected GTextField userTF;
|
||||
protected JTextField sourceTF, warnTA;
|
||||
|
||||
// State vars
|
||||
protected Credential myCredential;
|
||||
protected Result eResult;
|
||||
protected Boolean isReset;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public CredentialPanel(Component aParent)
|
||||
{
|
||||
super(aParent);
|
||||
|
||||
// State vars
|
||||
myCredential = null;
|
||||
eResult = null;
|
||||
isReset = true;
|
||||
|
||||
// Build the actual GUI
|
||||
buildGuiArea();
|
||||
updateGui();
|
||||
|
||||
// Set up some keyboard shortcuts
|
||||
FocusUtil.addAncestorKeyBinding(this, "ESCAPE", new ClickAction(ignoreB));
|
||||
}
|
||||
|
||||
public Credential getCredential()
|
||||
{
|
||||
return myCredential;
|
||||
}
|
||||
|
||||
public void setCredential(Credential aCredential, String aSourceUri)
|
||||
{
|
||||
// Construct the default (empty) credential
|
||||
if (aCredential == null)
|
||||
aCredential = new Credential("", null);
|
||||
|
||||
userTF.removeActionListener(this);
|
||||
userTF.setText(aCredential.getUsername());
|
||||
userTF.addActionListener(this);
|
||||
|
||||
passTF.removeActionListener(this);
|
||||
passTF.setText(aCredential.getPasswordAsString());
|
||||
passTF.addActionListener(this);
|
||||
|
||||
sourceTF.setText(aSourceUri);
|
||||
sourceTF.setCaretPosition(0);
|
||||
|
||||
// Reset the dialog
|
||||
isReset = true;
|
||||
EventQueue.invokeLater(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
updateGui();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void setTitle(String aTitle)
|
||||
{
|
||||
titleL.setText(aTitle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e)
|
||||
{
|
||||
Object source;
|
||||
|
||||
source = e.getSource();
|
||||
|
||||
if (source == ignoreB)
|
||||
{
|
||||
// Hide the dialog
|
||||
myCredential = null;
|
||||
setVisible(false);
|
||||
|
||||
// Notify our listeners
|
||||
notifyListeners(this, 0, "Ignore");
|
||||
}
|
||||
else if (source == acceptB || source == passTF)
|
||||
{
|
||||
// Set the GUI into the waiting mode
|
||||
isReset = null;
|
||||
updateGui();
|
||||
|
||||
// Validate the settings
|
||||
final Credential aCredential = new Credential(userTF.getText(), passTF.getPassword());
|
||||
final String uriRoot = sourceTF.getText();
|
||||
|
||||
new Thread()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
final Result aResult;
|
||||
|
||||
// Pause for 0.5 sec to let the user register the change
|
||||
try
|
||||
{
|
||||
Thread.sleep(500);
|
||||
}
|
||||
catch (InterruptedException aExp)
|
||||
{
|
||||
aExp.printStackTrace();
|
||||
}
|
||||
|
||||
// Test the credentials
|
||||
aResult = NetUtil.checkCredentials(uriRoot, aCredential);
|
||||
|
||||
// Update the Gui
|
||||
EventQueue.invokeLater(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
// Bail if the user decided to quit before our results came
|
||||
// back.
|
||||
if (isVisible() == false)
|
||||
return;
|
||||
|
||||
// If the credentials are valid then save them and bail
|
||||
if (aResult == Result.Success)
|
||||
{
|
||||
myCredential = aCredential;
|
||||
setVisible(false);
|
||||
|
||||
// Notify our listeners
|
||||
notifyListeners(CredentialPanel.this, 0, "Accept");
|
||||
}
|
||||
// Try again
|
||||
else
|
||||
{
|
||||
eResult = aResult;
|
||||
isReset = false;
|
||||
updateGui();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
else
|
||||
{
|
||||
updateGui();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct the GUI
|
||||
*/
|
||||
private void buildGuiArea()
|
||||
{
|
||||
Dimension aDimension;
|
||||
JLabel tmpL;
|
||||
String aStr;
|
||||
|
||||
// Form the grid bag constraints
|
||||
setLayout(new MigLayout("", "[right][grow][][]"));
|
||||
|
||||
// Title Area
|
||||
titleL = new JLabel("Product Name", JLabel.CENTER);
|
||||
add(titleL, "growx,span 4,wrap");
|
||||
|
||||
// Source area
|
||||
tmpL = new JLabel("Source:");
|
||||
add(tmpL);
|
||||
|
||||
sourceTF = GuiUtil.createUneditableTextField("http://www.google.edu");
|
||||
add(sourceTF, "growx,span 3,wrap");
|
||||
|
||||
// Username area
|
||||
tmpL = new JLabel("Username:");
|
||||
userTF = new GTextField(this);
|
||||
add(tmpL);
|
||||
add(userTF, "growx,span 3,wrap");
|
||||
|
||||
// Password area
|
||||
tmpL = new JLabel("Password:");
|
||||
passTF = new GPasswordField(this);
|
||||
add(tmpL);
|
||||
add(passTF, "growx,span 3,wrap");
|
||||
|
||||
// Warn area
|
||||
aStr = "Please enter the credentials for accessing the data.";
|
||||
warnTA = GuiUtil.createUneditableTextField(aStr);
|
||||
warnTA.setForeground(warnColor);
|
||||
add(warnTA, "growx,span 4,wrap");
|
||||
|
||||
// Action area
|
||||
aDimension = GuiUtil.computePreferredJButtonSize("Ignore", "Accept");
|
||||
ignoreB = GuiUtil.createJButton("Ignore", this, aDimension);
|
||||
acceptB = GuiUtil.createJButton("Accept", this, aDimension);
|
||||
add(ignoreB, "skip 2,span 1");
|
||||
add(acceptB, "span 1");
|
||||
|
||||
setBorder(new BevelBorder(BevelBorder.RAISED));
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to update the GUI
|
||||
*/
|
||||
private void updateGui()
|
||||
{
|
||||
boolean isEnabled;
|
||||
|
||||
if (isReset == null)
|
||||
{
|
||||
warnTA.setText("Checking the credentials...");
|
||||
isEnabled = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (userTF.getText().isEmpty() == true && passTF.getPassword().length < 2)
|
||||
isReset = true;
|
||||
|
||||
isEnabled = true;
|
||||
if (isReset == true)
|
||||
{
|
||||
warnTA.setText("Please enter the credentials for accessing the data.");
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (eResult)
|
||||
{
|
||||
case BadCredentials:
|
||||
warnTA.setText("Credentials are invalid.");
|
||||
break;
|
||||
|
||||
case ConnectFailure:
|
||||
warnTA.setText("Failed to connect to resource.");
|
||||
break;
|
||||
|
||||
case UnreachableHost:
|
||||
warnTA.setText("Unreachable host.");
|
||||
break;
|
||||
|
||||
default:
|
||||
warnTA.setText("Unreconzied error. Error: " + eResult);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update the UI elements
|
||||
userTF.setEnabled(isEnabled);
|
||||
passTF.setEnabled(isEnabled);
|
||||
acceptB.setEnabled(isEnabled);
|
||||
}
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user