- /**
- * A helper class for properties of Box which require special
- * handling.
- *
- * To avoid excessive use of String.equals(), the Box.get() and
- * Box.put() methods employ a Hash keyed on property names that
- * require special handling. The value stored in the Hash is an
- * instance of an anonymous subclass of SpecialBoxProperty, which knows
- * how to handle get()s and put()s for that property name. There
- * should be one anonymous subclass of SpecialBoxProperty for each
- * specially-handled property on Box.
- */
- static class SpecialBoxProperty {
-
- SpecialBoxProperty() { }
-
- /** stores instances of SpecialBoxProperty; keyed on property name */
- static Hash specialBoxProperties = new Hash(200, 3);
-
- /** this method defines the behavior when the property is get()ed from b */
- Object get(Box b) { return null; }
-
- /** this method defines the behavior when the property is put() to b */
- void put(Box b, Object value) { }
-
- /** this method defines the behavior when the property is put() to b, allows a single SpecialBoxProperty to serve multiple properties */
- void put(String name, Box b, Object value) { put(b, value); }
-
- static {
- specialBoxProperties.put("fill", new ColorBoxProperty() {
- public void put(final Box b, final Object value) {
- if (value == null || !(value instanceof Res)) super.put(b, value);
- else {
- Callback callback = new Callback() { public Object call(Object pic) {
- b.image = (Picture)pic;
- b.minwidth = b.image.getWidth();
- b.minheight = b.image.getHeight();
- MARK_FOR_REFLOW_b;
- b.dirty();
- return null;
- } };
- Picture pic = Picture.fromRes((Res)value, callback);
- if (pic != null) callback.call(pic);
- }
- }
- public int getColor(Box b) { return b.fillcolor; }
- public void putColor(Box b, int argb) { b.fillcolor = argb; }
- });
- specialBoxProperties.put("textcolor", new ColorBoxProperty() {
- public int getColor(Box b) { return b.textcolor; }
- public void putColor(Box b, int argb) { b.textcolor = argb; }
- });
- specialBoxProperties.put("strokecolor", new ColorBoxProperty() {
- public int getColor(Box b) { return b.strokecolor; }
- public void putColor(Box b, int argb) { b.strokecolor = argb; }
- });
-
- specialBoxProperties.put("text", new SpecialBoxProperty() {
- public Object get(Box b) { return b.text; }
- public void put(Box b, Object value) {
- String t = value == null ? "null" : value.toString();
- if (t.equals(b.text)) return;
- b.text = t;
- b.dirty();
- b.recompute_font();
- } });
-
- specialBoxProperties.put("path", new SpecialBoxProperty() {
- public Object get(Box b) { throw new JS.Exn("cannot read from the path property"); }
- public void put(Box b, Object value) {
- String t = value == null ? "null" : value.toString();
- b.path = value == null ? null : VectorGraphics.parseVectorPath(value.toString());
- MARK_FOR_REFLOW_b;
- b.dirty();
- } });
-
- specialBoxProperties.put("transform", new SpecialBoxProperty() {
- public void put(Box b, Object value) {
- String t = value.toString().trim();
- b.transform = VectorGraphics.Affine.identity();
- while (t.length() > 0) {
- if (t.startsWith("skewX(")) {
- // FIXME
-
- } else if (t.startsWith("shear(")) {
- // FIXME: nonstandard; remove this
- b.transform.multiply(VectorGraphics.Affine.shear(Float.parseFloat(t.substring(t.indexOf('(') + 1, t.indexOf(')')))));
-
- } else if (t.startsWith("skewY(")) {
- // FIXME
-
- } else if (t.startsWith("rotate(")) {
- String sub = t.substring(t.indexOf('(') + 1, t.indexOf(')'));
- if (sub.indexOf(',') != -1) {
- float angle = Float.parseFloat(sub.substring(0, sub.indexOf(',')));
- sub = sub.substring(sub.indexOf(',') + 1);
- float cx = Float.parseFloat(sub.substring(0, sub.indexOf(',')));
- sub = sub.substring(sub.indexOf(',') + 1);
- float cy = Float.parseFloat(sub);
- b.transform.multiply(VectorGraphics.Affine.translate(cx, cy));
- b.transform.multiply(VectorGraphics.Affine.rotate(angle));
- b.transform.multiply(VectorGraphics.Affine.translate(-1 * cx, -1 * cy));
- } else {
- b.transform.multiply(VectorGraphics.Affine.rotate(Float.parseFloat(t.substring(t.indexOf('(') + 1, t.indexOf(')')))));
- }
-
- } else if (t.startsWith("translate(")) {
- String sub = t.substring(t.indexOf('(') + 1, t.indexOf(')'));
- if (sub.indexOf(',') > -1) {
- b.transform.multiply(VectorGraphics.Affine.translate(Float.parseFloat(t.substring(t.indexOf('(') + 1, t.indexOf(','))),
- Float.parseFloat(t.substring(t.indexOf(',') + 1, t.indexOf(')')))));
- } else {
- b.transform.multiply(VectorGraphics.Affine.translate(Float.parseFloat(t.substring(t.indexOf('(') + 1, t.indexOf(','))), 0));
- }
-
- } else if (t.startsWith("flip(")) {
- String which = t.substring(t.indexOf('(') + 1, t.indexOf(')'));
- b.transform.multiply(VectorGraphics.Affine.flip(which.equals("horizontal"), which.equals("vertical")));
-
- } else if (t.startsWith("scale(")) {
- String sub = t.substring(t.indexOf('(') + 1, t.indexOf(')'));
- if (sub.indexOf(',') > -1) {
- b.transform.multiply(VectorGraphics.Affine.scale(Float.parseFloat(t.substring(t.indexOf('(') + 1, t.indexOf(','))),
- Float.parseFloat(t.substring(t.indexOf(',') + 1, t.indexOf(')')))));
- } else {
- b.transform.multiply(VectorGraphics.Affine.scale(Float.parseFloat(t.substring(t.indexOf('(') + 1, t.indexOf(','))),
- Float.parseFloat(t.substring(t.indexOf('(') + 1, t.indexOf(',')))));
- }
-
- } else if (t.startsWith("matrix(")) {
- // FIXME: is this mapped right?
- float d[] = new float[6];
- StringTokenizer st = new StringTokenizer(t, ",", false);
- for(int i=0; i<6; i++)
- d[i] = Float.parseFloat(st.nextToken());
- b.transform.multiply(new VectorGraphics.Affine(d[0], d[1], d[2], d[3], d[4], d[5]));
- }
- t = t.substring(t.indexOf(')') + 1).trim();
- }
- MARK_FOR_REFLOW_b;
- b.dirty();
- }
- public Object get(Box b) { return b.transform.toString(); }
- });
-
- specialBoxProperties.put("font", new SpecialBoxProperty() {
- public Object get(Box b) { return b.font; }
- public void put(Box b, Object value) {
- // FIXME: translate value into a resource if it is a string
- b.font = value == null ? null :
- Font.getFont((Res)value, b.font == null ? 10 : b.font.pointsize); // FIXME
- MARK_FOR_REFLOW_b;
- b.flags |= FONT_CHANGED_FLAG;
- b.dirty();
- b.recompute_font();
- } });
-
- specialBoxProperties.put("fontsize", new SpecialBoxProperty() {
- public Object get(Box b) { return b.font; }
- public void put(Box b, Object value) {
- if (b.font != null && b.font.pointsize == stoi(value)) return;
- b.font = value == null ? null :
- Font.getFont(b.font == null ? null : b.font.res, stoi(value)); // FIXME
- MARK_FOR_REFLOW_b;
- b.flags |= FONT_CHANGED_FLAG;
- b.dirty();
- b.recompute_font();
- } });
-
- specialBoxProperties.put("strokewidth", new SpecialBoxProperty() {
- public Object get(Box b) { return new Integer(b.strokewidth); }
- public void put(Box b, Object value) {
- if (b.strokewidth == stoi(value)) return;
- b.strokewidth = stoi(value);
- b.dirty();
- } });
-
- specialBoxProperties.put("align", new SpecialBoxProperty() {
- public Object get(Box b) {
- switch(b.flags & ALIGN_FLAGS) {
- case (ALIGN_TOP_FLAG | ALIGN_LEFT_FLAG): return "topleft";
- case (ALIGN_BOTTOM_FLAG | ALIGN_LEFT_FLAG): return "bottomleft";
- case (ALIGN_TOP_FLAG | ALIGN_RIGHT_FLAG): return "topright";
- case (ALIGN_BOTTOM_FLAG | ALIGN_RIGHT_FLAG): return "bottomright";
- case ALIGN_TOP_FLAG: return "top";
- case ALIGN_BOTTOM_FLAG: return "bottom";
- case ALIGN_LEFT_FLAG: return "left";
- case ALIGN_RIGHT_FLAG: return "right";
- case 0: return "center";
- default: throw new Error("invalid alignment flags: " + (b.flags & ALIGN_FLAGS));
- }
- }
- public void put(Box b, Object value) {
- b.flags &= ~ALIGN_FLAGS;
- if (value == null || value.equals("center")) { b.flags &= ALIGN_FLAGS; }
- else if (value.equals("topleft")) { b.flags |= ALIGN_TOP_FLAG | ALIGN_LEFT_FLAG; }
- else if (value.equals("bottomleft")) { b.flags |= ALIGN_BOTTOM_FLAG | ALIGN_LEFT_FLAG; }
- else if (value.equals("topright")) { b.flags |= ALIGN_TOP_FLAG | ALIGN_RIGHT_FLAG; }
- else if (value.equals("bottomright")) { b.flags |= ALIGN_BOTTOM_FLAG | ALIGN_RIGHT_FLAG; }
- else if (value.equals("top")) { b.flags |= ALIGN_TOP_FLAG; }
- else if (value.equals("bottom")) { b.flags |= ALIGN_BOTTOM_FLAG; }
- else if (value.equals("left")) { b.flags |= ALIGN_LEFT_FLAG; }
- else if (value.equals("right")) { b.flags |= ALIGN_RIGHT_FLAG; }
- else Log.logJS("invalid alignment specifier \"" + value + "\"");
- MARK_FOR_REFLOW_b;
- b.dirty();
- } });
-
- specialBoxProperties.put("thisbox", new SpecialBoxProperty() {
- public Object get(Box b) { return b; }
- public void put(Box b, Object value) {
- if (value == null) b.remove();
- else if (Log.on) Log.log(this, "put invalid value to 'thisbox' property: " + value);
- }
- });
-
- specialBoxProperties.put("orient", new SpecialBoxProperty() {
- public Object get(Box b) {
- Log.log(this, "warning: the orient property is deprecated");
- if (b.redirect == null) return "horizontal";
- else if (b.redirect != b) return get(b.redirect);
- else if (b.cols == 1) return "vertical";
- else if (b.rows == 1) return "horizontal";
- else return "grid";
- }
- public void put(Box b, Object value) {
- Log.log(this, "warning: the orient property is deprecated");
- if (value == null) return;
- if (b.redirect == null) return;
- if (b.redirect != b) { put(b.redirect, value); return; }
- if (value.equals("vertical")) {
- if (b.rows == 0) return;
- b.rows = 0; b.cols = 1;
- } else if (value.equals("horizontal")) {
- if (b.cols == 0) return;
- b.cols = 0; b.rows = 1;
- } else if (Log.on)
- Log.log(this, "invalid value put to orient property: " + value);
- MARK_FOR_REFLOW_b;
- } });
-
- specialBoxProperties.put("shrink", new SpecialBoxProperty() {
- public Object get(Box b) { return (((b.flags & HSHRINK_FLAG) != 0) || ((b.flags & VSHRINK_FLAG) != 0)) ? Boolean.TRUE : Boolean.FALSE; }
- public void put(Box b, Object value) { b.put("hshrink", value); b.put("vshrink", value); }
- });
-
- //#repeat hshrink/vshrink HSHRINK_FLAG/VSHRINK_FLAG
- specialBoxProperties.put("hshrink", new SpecialBoxProperty() {
- public Object get(Box b) { return new Boolean((b.flags & HSHRINK_FLAG) != 0); }
- public void put(Box b, Object value) {
- boolean newshrink = stob(value);
- if (((b.flags & HSHRINK_FLAG) != 0) == newshrink) return;
- if (newshrink) b.flags |= HSHRINK_FLAG; else b.flags &= ~HSHRINK_FLAG;
- MARK_FOR_REFLOW_b;
- }
- });
- //#end
-
- //#repeat x/y
- specialBoxProperties.put("x", new SpecialBoxProperty() {
- public Object get(Box b) {
- if (b.surface == null) return new Integer(0);
- if ((b.flags & INVISIBLE_FLAG) != 0) return new Integer(0);
- return new Integer(b.x);
- }
- public void put(Box b, Object value) {
- if (!((b.flags & NOTPACKED_FLAG) != 0) && (b.parent != null || b.surface == null)) return;
- int x = stoi(value);
- if (x == b.x) return;
- b.dirty();
- b.x = x;
- if (b.parent == null && b.surface != null) b.surface.setLocation();
- MARK_FOR_REFLOW_b;
- b.dirty();
- }
- });
- //#end
-
- //#repeat width/height height/width minwidth/minheight maxwidth/maxheight true/false
- specialBoxProperties.put("width", new SpecialBoxProperty() {
- public Object get(Box b) { return new Integer(b.width); }
- public void put(Box b, Object value) {
- int newval = stoi(value);
- if (b.parent == null && b.surface != null) {
- // hack to circumvent #repeat
- int other = b.height;
- if (true) b.surface.setSize(newval, other);
- else b.surface.setSize(other, newval);
- MARK_FOR_REFLOW_b;
- } else {
- if (b.minwidth == newval && b.maxwidth == newval) return;
- b.minwidth = b.maxwidth = newval;
- MARK_FOR_REFLOW_b;
- }
- } });
- //#end