annotate src/samer/core_/X.java @ 8:5e3cbbf173aa tip

Reorganise some more
author samer
date Fri, 05 Apr 2019 22:41:58 +0100
parents bf79fb79ee13
children
rev   line source
samer@0 1 /*
samer@0 2 * X.java
samer@0 3 *
samer@0 4 * Copyright (c) 2001, Samer Abdallah, King's College London.
samer@0 5 * All rights reserved.
samer@0 6 *
samer@0 7 * This software is provided AS IS and WITHOUT ANY WARRANTY;
samer@0 8 * without even the implied warranty of MERCHANTABILITY or
samer@0 9 * FITNESS FOR A PARTICULAR PURPOSE.
samer@0 10 */
samer@0 11
samer@0 12 package samer.core;
samer@0 13 import java.io.StringWriter;
samer@0 14 import java.util.StringTokenizer;
samer@0 15 import java.awt.Font;
samer@0 16 import java.awt.Rectangle;
samer@0 17 import java.awt.Color;
samer@0 18 import java.awt.SystemColor;
samer@0 19
samer@0 20 import samer.core.Environment.Datum;
samer@0 21 import samer.core.Environment.Codec;
samer@0 22 import samer.core.Environment.Autocoder;
samer@0 23
samer@0 24 /**
samer@0 25 Static methods for converting objects and extracting correctly typed
samer@0 26 values from Environments. Short name
samer@0 27 because of expected frequent use! Also, contains
samer@0 28 several Codec classes.
samer@0 29 @see samer.core.Environment
samer@0 30 @see samer.core.Environment.Datum
samer@0 31 @see samer.core.Environment.Autocoder
samer@0 32 */
samer@0 33
samer@0 34 public class X
samer@0 35 {
samer@0 36 /** Tries to extract an Object from the given Datum, throws Exception in failure */
samer@0 37 public static Object object(Datum b) throws Exception {
samer@0 38 Object ret=b.get(ObjectCodec,null);
samer@0 39 if (ret==null) throw new Exception("no data");
samer@0 40 return ret;
samer@0 41 }
samer@0 42
samer@0 43 /** Tries to extract a String given Datum */
samer@0 44 public static String string(Datum b) throws Exception {
samer@0 45 String ret=(String)b.get(StringCodec,null);
samer@0 46 if (ret==null) throw new Exception("datum has no value");
samer@0 47 return ret;
samer@0 48 }
samer@0 49
samer@0 50 /** Tries to extract a Font given Datum. If this fails, tries
samer@0 51 to decode def using FontCodec. def can be a Font or a String. */
samer@0 52 public static Font font(Datum b, Object def) {
samer@0 53 return (Font)b.get(FontCodec,def);
samer@0 54 }
samer@0 55
samer@0 56 /** Tries to extract a Rectangle from given Datum. If this fails, tries
samer@0 57 to decode def as a rectangle. */
samer@0 58 public static Rectangle rect(Datum b, Rectangle def) {
samer@0 59 return (Rectangle)b.get(RectangleCodec,def);
samer@0 60 }
samer@0 61
samer@0 62 /** Get String from Datum, returning def if this fails */
samer@0 63 public static String string(Datum b,String def) {
samer@0 64 return (String)b.get(StringCodec,def);
samer@0 65 }
samer@0 66
samer@0 67 /** Get Color from Datum, decoding def if this fails. def can
samer@0 68 be a Color or a String. See ColorCodec. */
samer@0 69 public static Color color(Datum b, Object def) {
samer@0 70 return (Color)b.get(ColorCodec,def);
samer@0 71 }
samer@0 72
samer@0 73 /** Extract int from Datum */
samer@0 74 public static int _int(Datum b,int def) {
samer@0 75 return ((Integer)b.get(IntegerCodec,new Integer(def))).intValue();
samer@0 76 }
samer@0 77 /** Extract double from Datum */
samer@0 78 public static double _double(Datum b,double def) {
samer@0 79 return ((Double)b.get(DoubleCodec,new Double(def))).doubleValue();
samer@0 80 }
samer@0 81 /** Extract boolean from Datum */
samer@0 82 public static boolean _bool(Datum b,boolean def) {
samer@0 83 return ((Boolean)b.get(BooleanCodec,new Boolean(def))).booleanValue();
samer@0 84 }
samer@0 85
samer@0 86 /** store given object to current environment */
samer@0 87 public static void store(String name, Object value) {
samer@0 88 Shell.env().store(name,value,codec(value));
samer@0 89 }
samer@0 90
samer@0 91 /** Extracts an integer array from a string. Valid strings are, eg
samer@0 92 "(1,2,3)", "(4 5 6)", "7 8 9", "10, 11, 12" */
samer@0 93 public static int[] parseIntArray(String s, int n)
samer@0 94 {
samer@0 95 StringTokenizer token = new StringTokenizer(s,"(), ");
samer@0 96 int[] a=new int[n];
samer@0 97
samer@0 98 for (int i=0; i<n; i++) {
samer@0 99 a[i]=Integer.parseInt(token.nextToken());
samer@0 100 }
samer@0 101 return a;
samer@0 102 }
samer@0 103
samer@0 104 /** @see samer.core.X.parseIntArray */
samer@0 105 public static double[] doubleArray(String s, int n)
samer@0 106 {
samer@0 107 StringTokenizer token = new StringTokenizer(s,"(), ");
samer@0 108 double[] a=new double[n];
samer@0 109
samer@0 110 for (int i=0; i<n; i++) {
samer@0 111 a[i]=parseDouble(token.nextToken());
samer@0 112 }
samer@0 113 return a;
samer@0 114 }
samer@0 115
samer@0 116 /** Sets each integer in the int array to the numeric value of the corresponding
samer@0 117 Objects in the Object array (they have to be subclasses of Numbe).
samer@0 118 */
samer@0 119 public static void setIntArray(int[] a, Object[] b) {
samer@0 120 for (int i=0; i<a.length; i++)
samer@0 121 a[i]=((Number)b[i]).intValue();
samer@0 122 }
samer@0 123
samer@0 124 /** Base class for objects that can convert some type to and from String or
samer@0 125 Object. @see samer.core.Environment.Codec */
samer@0 126 public static class BaseCodec implements Codec
samer@0 127 {
samer@0 128 public Class targetClass() { return Object.class; }
samer@0 129
samer@0 130 /** convert to string using object's toString() method (a reasonable default) */
samer@0 131 public String string(Object o) { return o.toString(); }
samer@0 132
samer@0 133 /** Convert to object by returning original object. This might be OK for
samer@0 134 * immutable objects, but should be overriden for mutable ones, perhaps
samer@0 135 * returning a clone of the original or an object of a different class altogether.
samer@0 136 */
samer@0 137 public Object object(Object o) { return o; }
samer@0 138
samer@0 139 /** Decode given object to by return it the given object itself. */
samer@0 140 public Object decode(Object o) { return o; }
samer@0 141 };
samer@0 142
samer@0 143 public static Codec ObjectCodec = new BaseCodec();
samer@0 144
samer@0 145 /** Can decode numbers in Integer, Number, or String form */
samer@0 146 public static Codec IntegerCodec = new BaseCodec()
samer@0 147 {
samer@0 148 public Class targetClass() { return Integer.class; }
samer@0 149
samer@0 150 /** If given object is any subclass of java.lang.Number, then its
samer@0 151 numerical value is returned as an Integer. If it is a string,
samer@0 152 the string is parsed to extract an integer value. Any other
samer@0 153 class will probably cause this function to barf.
samer@0 154 */
samer@0 155
samer@0 156 public Object decode(Object o) {
samer@0 157 // if (o==null) return null;
samer@0 158 if (o instanceof Integer) return o;
samer@0 159 if (o instanceof String) return Integer.decode(o.toString());
samer@0 160 return new Integer(((Number)o).intValue());
samer@0 161 }
samer@0 162 };
samer@0 163
samer@0 164 private static DoubleFormat fmt=new DoubleFormat(3);
samer@0 165
samer@0 166 /** Convert double to string using the (private) current DoubleFormat object */
samer@0 167 public static String string(double v) { return fmt._format(v); }
samer@0 168
samer@0 169 /** Convert string to double */
samer@0 170 public static double parseDouble(String s) {
samer@0 171 return Double.valueOf(s).doubleValue();
samer@0 172 }
samer@0 173
samer@0 174 /** Can decode numbers in Double, Number, or String form */
samer@0 175 public static Codec DoubleCodec = new BaseCodec()
samer@0 176 {
samer@0 177 public Class targetClass() { return Double.class; }
samer@0 178
samer@0 179 public String string(Object o) { return fmt._format(((Number)o).doubleValue()); }
samer@0 180
samer@0 181 /** Can decode String or any subclass of Number */
samer@0 182 public Object decode(Object o) {
samer@0 183 // if (o==null) return null;
samer@0 184 if (o instanceof Double) return o;
samer@0 185 if (o instanceof String) return Double.valueOf(o.toString());
samer@0 186 return new Double(((Number)o).doubleValue());
samer@0 187 }
samer@0 188
samer@0 189 };
samer@0 190
samer@0 191 /** Can decode Boolean or String ("true" or "false") form */
samer@0 192 public static Codec BooleanCodec = new BaseCodec()
samer@0 193 {
samer@0 194 public Class targetClass() { return Boolean.class; }
samer@0 195 public Object decode(Object o) {
samer@0 196 // if (o==null) return null;
samer@0 197 if (o instanceof Boolean) return o;
samer@0 198 return Boolean.valueOf(o.toString());
samer@0 199 }
samer@0 200 };
samer@0 201
samer@0 202 public static Codec StringCodec = new BaseCodec()
samer@0 203 {
samer@0 204 public Class targetClass() { return String.class; }
samer@0 205 public Object decode(Object o) {
samer@0 206 // if (o==null) return null;
samer@0 207 if (o instanceof String) return o;
samer@0 208 else return o.toString();
samer@0 209 }
samer@0 210 };
samer@0 211
samer@0 212
samer@0 213 /** Can decode Color or String form
samer@0 214 String can be "#rrggbb" where rrggbb are hex,
samer@0 215 or "(r,g,b)" or "(r g b)" where r, g, b are integers,
samer@0 216 or "$bg", which evaluates to SystemColor.control, the
samer@0 217 default background color for components,
samer@0 218 or "$fg", which evaluates to SystemColor.controlText,
samer@0 219 the default foreground color.
samer@0 220 */
samer@0 221
samer@0 222 public static Codec ColorCodec = new Codec()
samer@0 223 {
samer@0 224 public Class targetClass() { return Color.class; }
samer@0 225 public Object object(Object o) { return o; }
samer@0 226 public String string(Object o) {
samer@0 227 StringBuffer buf=new StringBuffer("#");
samer@0 228 buf.append(Integer.toHexString(((Color)o).getRGB() & 0xffffff));
samer@0 229 return buf.toString();
samer@0 230 }
samer@0 231 public Object decode(Object o) {
samer@0 232 // if (o==null) return null;
samer@0 233 if (o instanceof Color) return o;
samer@0 234
samer@0 235 String s=o.toString();
samer@0 236 if (s.startsWith("(")) {
samer@0 237 int[] a=parseIntArray(s,3);
samer@0 238 return new Color(a[0],a[1],a[2]);
samer@0 239 }
samer@0 240 if (s.equals("$bg")) return SystemColor.control;
samer@0 241 if (s.equals("$fg")) return SystemColor.controlText;
samer@0 242 return Color.decode(s);
samer@0 243 }
samer@0 244 };
samer@0 245
samer@0 246 /** Can decode Font or String, using Font.decode(),
samer@0 247 eg "Helvetica-PLAIN-12" */
samer@0 248 public static Codec FontCodec = new Codec()
samer@0 249 {
samer@0 250 public Class targetClass() { return Font.class; }
samer@0 251 public Object object(Object o) { return o; }
samer@0 252 public String string(Object o) { return o.toString(); }
samer@0 253 public Object decode(Object o) {
samer@0 254 // if (o==null) return null;
samer@0 255 if (o instanceof Font) return o;
samer@0 256 return Font.decode(o.toString());
samer@0 257 }
samer@0 258 };
samer@0 259
samer@0 260 public static Codec RectangleCodec = new Codec()
samer@0 261 {
samer@0 262 public Class targetClass() { return Font.class; }
samer@0 263 public Object object(Object o) { return o; }
samer@0 264 public String string(Object o) {
samer@0 265 Rectangle r=(Rectangle)o;
samer@0 266 StringBuffer buf=new StringBuffer();
samer@0 267
samer@0 268 buf.append('(');
samer@0 269 buf.append(String.valueOf(r.x)); buf.append(',');
samer@0 270 buf.append(String.valueOf(r.y)); buf.append(',');
samer@0 271 buf.append(String.valueOf(r.width)); buf.append(',');
samer@0 272 buf.append(String.valueOf(r.height));
samer@0 273 buf.append(')');
samer@0 274 return buf.toString();
samer@0 275 }
samer@0 276
samer@0 277 public Object decode(Object o) {
samer@0 278 // if (o==null) return null;
samer@0 279 if (o instanceof Rectangle) return o;
samer@0 280
samer@0 281 int[] a=parseIntArray(o.toString(),4);
samer@0 282 return new Rectangle(a[0],a[1],a[2],a[3]);
samer@0 283 }
samer@0 284 };
samer@0 285
samer@0 286 public static Codec codec(Object o) { return codec(o.getClass()); }
samer@0 287 public static Codec codec(Class c)
samer@0 288 {
samer@0 289 for (int i=classes.length-1; i>0; i--) {
samer@0 290 if (classes[i].isAssignableFrom(c)) return codecs[i];
samer@0 291 }
samer@0 292 return codecs[0];
samer@0 293 }
samer@0 294
samer@0 295 private static Class[] classes = {
samer@0 296 Object.class,
samer@0 297 Font.class,
samer@0 298 Rectangle.class,
samer@0 299 Color.class,
samer@0 300 String.class,
samer@0 301 Boolean.class,
samer@0 302 Integer.class,
samer@0 303 Double.class
samer@0 304 };
samer@0 305
samer@0 306 private static Codec[] codecs = {
samer@0 307 ObjectCodec,
samer@0 308 FontCodec,
samer@0 309 RectangleCodec,
samer@0 310 ColorCodec,
samer@0 311 StringCodec,
samer@0 312 BooleanCodec,
samer@0 313 IntegerCodec,
samer@0 314 DoubleCodec
samer@0 315 };
samer@0 316 }
samer@0 317