1 // Copyright 2002 Adam Megacz, see the COPYING file for licensing [GPL]
11 * A helper class for properties of Box which require special
14 * To avoid excessive use of String.equals(), the Box.get() and
15 * Box.put() methods employ a Hash keyed on property names that
16 * require special handling. The value stored in the Hash is an
17 * instance of an anonymous subclass of SpecialBoxProperty, which knows
18 * how to handle get()s and put()s for that property name. There
19 * should be one anonymous subclass of SpecialBoxProperty for each
20 * specially-handled property on Box.
22 class SpecialBoxProperty {
24 SpecialBoxProperty() { }
25 private static final int NUMINTS = Box.NUMINTS;
26 private static final int dmax = Box.dmax;
27 private static final int dmin = Box.dmin;
28 private static final int cmin = Box.cmin;
29 private static final int abs = Box.abs;
30 private static final int pos = Box.pos;
31 private static final int size = Box.size;
32 private static final int oldpos = Box.oldpos;
33 private static final int oldsize = Box.oldsize;
34 private static final int pad = Box.pad;
36 /** stores instances of SpecialBoxProperty; keyed on property name */
37 static Hash specialBoxProperties = new Hash(200, 3);
39 /** this method defines the behavior when the property is get()ed from b */
40 Object get(Box b) { return null; }
42 /** this method defines the behavior when the property is put() to b */
43 void put(Box b, Object value) { }
45 /** this method defines the behavior when the property is put() to b, allows a single SpecialBoxProperty to serve multiple properties */
46 void put(String name, Box b, Object value) { put(b, value); }
48 // 'ye olde IBM CGA colours', as defined in the XWT reference
49 static final int black = 0xFF000000;
50 static final int blue = 0xFF000088;
51 static final int green = 0xFF008800;
52 static final int cyan = 0xFF008888;
53 static final int red = 0xFF880000;
54 static final int magenta = 0xFF880088;
55 static final int brown = 0xFF888800;
56 static final int lightGray = 0xFFBDBEBD;
57 static final int darkGray = 0xFF242424;
58 static final int brightBlue = 0xFF0000FF;
59 static final int brightGreen = 0xFF00FF00;
60 static final int brightCyan = 0xFF00FFFF;
61 static final int brightRed = 0xFFFF0000;
62 static final int pink = 0xFFFF00FF;
63 static final int yellow = 0xFFFFFF00;
64 static final int white = 0xFFFFFFFF;
70 private static void init() {
71 specialBoxProperties.put("color", new SpecialBoxProperty() {
72 public Object get(Box b) {
73 if ((b.color & 0xFF000000) == 0) return null;
74 String red = Integer.toHexString((b.color & 0x00FF0000) >> 16);
75 String green = Integer.toHexString((b.color & 0x0000FF00) >> 8);
76 String blue = Integer.toHexString(b.color & 0x000000FF);
77 if (red.length() < 2) red = "0" + red;
78 if (blue.length() < 2) blue = "0" + blue;
79 if (green.length() < 2) green = "0" + green;
80 return "#" + red + green + blue;
82 public void put(Box b, Object value) {
83 int newcolor = b.color;
84 String s = value == null ? null : value.toString();
85 if (value == null) newcolor = 0x00000000;
86 else if (s.length() > 0 && s.charAt(0) == '#')
88 newcolor = 0xFF000000 |
89 (Integer.parseInt(s.substring(1, 3), 16) << 16) |
90 (Integer.parseInt(s.substring(3, 5), 16) << 8) |
91 Integer.parseInt(s.substring(5, 7), 16);
92 } catch (NumberFormatException e) {
93 Log.log(this, "invalid color " + s);
96 else if (s.equals("black")) newcolor = black;
97 else if (s.equals("blue")) newcolor = blue;
98 else if (s.equals("green")) newcolor = green;
99 else if (s.equals("cyan")) newcolor = cyan;
100 else if (s.equals("red")) newcolor = red;
101 else if (s.equals("magenta")) newcolor = magenta;
102 else if (s.equals("brown")) newcolor = brown;
103 else if (s.equals("lightGray")) newcolor = lightGray;
104 else if (s.equals("darkGray")) newcolor = darkGray;
105 else if (s.equals("brightBlue")) newcolor = brightBlue;
106 else if (s.equals("brightGreen")) newcolor = brightGreen;
107 else if (s.equals("brightCyan")) newcolor = brightCyan;
108 else if (s.equals("brightRed")) newcolor = brightRed;
109 else if (s.equals("pink")) newcolor = pink;
110 else if (s.equals("yellow")) newcolor = yellow;
111 else if (s.equals("white")) newcolor = white;
112 else if (Log.on) Log.logJS(this, "invalid color \"" + s + "\"");
113 if (newcolor == b.color) return;
119 specialBoxProperties.put("textcolor", new SpecialBoxProperty() {
120 public Object get(Box b) {
121 if ((b.textcolor & 0xFF000000) == 0) return null;
122 String red = Integer.toHexString((b.textcolor & 0x00FF0000) >> 16);
123 String green = Integer.toHexString((b.textcolor & 0x0000FF00) >> 8);
124 String blue = Integer.toHexString(b.textcolor & 0x000000FF);
125 if (red.length() < 2) red = "0" + red;
126 if (blue.length() < 2) blue = "0" + blue;
127 if (green.length() < 2) green = "0" + green;
128 return "#" + red + green + blue;
130 public void put(Box b, Object value) {
131 int newtextcolor = b.color;
132 if (value == null) return;
133 String s = value.toString();
134 if (s.length() > 0 && s.charAt(0) == '#')
135 newtextcolor = 0xFF000000 |
136 (Integer.parseInt(s.substring(1, 3), 16) << 16) |
137 (Integer.parseInt(s.substring(3, 5), 16) << 8) |
138 Integer.parseInt(s.substring(5, 7), 16);
139 else if (s.equals("black")) newtextcolor = black;
140 else if (s.equals("blue")) newtextcolor = blue;
141 else if (s.equals("green")) newtextcolor = green;
142 else if (s.equals("cyan")) newtextcolor = cyan;
143 else if (s.equals("red")) newtextcolor = red;
144 else if (s.equals("magenta")) newtextcolor = magenta;
145 else if (s.equals("brown")) newtextcolor = brown;
146 else if (s.equals("lightGray")) newtextcolor = lightGray;
147 else if (s.equals("darkGray")) newtextcolor = darkGray;
148 else if (s.equals("brightBlue")) newtextcolor = brightBlue;
149 else if (s.equals("brightGreen")) newtextcolor = brightGreen;
150 else if (s.equals("brightCyan")) newtextcolor = brightCyan;
151 else if (s.equals("brightRed")) newtextcolor = brightRed;
152 else if (s.equals("pink")) newtextcolor = pink;
153 else if (s.equals("yellow")) newtextcolor = yellow;
154 else if (s.equals("white")) newtextcolor = white;
155 else if (Log.on) Log.logJS(this, "invalid color \"" + s + "\"");
156 if (newtextcolor == b.textcolor) return;
157 b.textcolor = newtextcolor;
161 specialBoxProperties.put("text", new SpecialBoxProperty() {
162 public Object get(Box b) { return b.text; }
163 public void put(Box b, Object value) {
164 String t = value == null ? "null" : value.toString();
165 if (t.equals(b.text)) return;
167 for(int i=0; i<t.length(); i++)
168 if (Character.isISOControl(t.charAt(i))) {
169 if (Log.on) Log.log(this,
170 "ISO Control characters are not permitted in box text strings; offending character is ASCII " +
175 // FEATURE: try removing the following line; it appears to be redundant
182 specialBoxProperties.put("thisbox", new SpecialBoxProperty() {
183 public Object get(Box b) { return b; }
184 public void put(Box b, Object value) {
185 if (value == null) b.remove();
186 else if (value.equals("window") || value.equals("frame")) {
187 if (b.redirect != b && Log.on)
188 Log.log(this, "WARNING: you have created a surface whose root box's redirect is not itself " +
189 "-- this isn't usually a good idea");
190 Platform.createSurface(b, value.equals("frame"), true);
191 } else if (Log.on) Log.log(this, "put invalid value to 'thisbox' property: " + value);
195 specialBoxProperties.put("orient", new SpecialBoxProperty() {
196 public Object get(Box b) {
197 if (b.redirect == null) return "horizontal";
198 else if (b.redirect != b) return get(b.redirect);
199 else if (b.o == 1) return "vertical";
200 else return "horizontal";
202 public void put(Box b, Object value) {
203 if (value == null) return;
204 if (b.redirect == null) return;
205 if (b.redirect != b) {
206 put(b.redirect, value);
209 if (value.equals("vertical")) {
210 if (b.o == 1) return;
213 } else if (value.equals("horizontal")) {
214 if (b.o == 0) return;
218 Log.log(this, "invalid value put to orient property: " + value);
219 b.mark_for_prerender();
220 b.sync_cmin_to_children();
223 specialBoxProperties.put("static", new SpecialBoxProperty() {
224 public Object get(Box b) {
225 String cfsn = JS.Thread.fromJavaThread(Thread.currentThread()).getCurrentCompiledFunction().getSourceName();
226 for(int i=0; i<cfsn.length() - 1; i++)
227 if (cfsn.charAt(i) == '.' && (cfsn.charAt(i+1) == '_' || Character.isDigit(cfsn.charAt(i+1)))) {
228 cfsn = cfsn.substring(0, i);
231 return Static.getStatic(cfsn);
233 public void put(Box b, Object value) { }
236 specialBoxProperties.put("sizetoimage", new SpecialBoxProperty() {
237 public Object get(Box b) { return b.sizetoimage ? Boolean.TRUE : Boolean.FALSE; }
238 public void put(Box b, Object value) {
240 if (b.sizetoimage) return;
241 b.sizetoimage = true;
244 b.sizetoimage = false;
248 specialBoxProperties.put("fixedaspect", new SpecialBoxProperty() {
249 public Object get(Box b) { return b.sizetoimage ? Boolean.TRUE : Boolean.FALSE; }
250 public void put(Box b, Object value) {
251 boolean newval = stob(value);
252 if (newval == b.fixedaspect) return;
253 b.fixedaspect = newval;
257 specialBoxProperties.put("shrink", new SpecialBoxProperty() {
258 public Object get(Box b) { return (b.vshrink && b.hshrink) ? Boolean.TRUE : Boolean.FALSE; }
259 public void put(Box b, Object value) {
260 boolean newshrink = stob(value);
261 if (b.hshrink == newshrink && b.vshrink == newshrink) return;
262 b.hshrink = b.vshrink = newshrink;
263 b.mark_for_prerender();
266 specialBoxProperties.put("hshrink", new SpecialBoxProperty() {
267 public Object get(Box b) { return new Boolean(b.hshrink); }
268 public void put(Box b, Object value) {
269 boolean newshrink = stob(value);
270 if (b.hshrink == newshrink) return;
271 b.hshrink = newshrink;
272 b.mark_for_prerender();
276 specialBoxProperties.put("vshrink", new SpecialBoxProperty() {
277 public Object get(Box b) { return b.vshrink ? Boolean.TRUE : Boolean.FALSE; }
278 public void put(Box b, Object value) {
279 boolean newshrink = stob(value);
280 if (b.vshrink == newshrink) return;
281 b.vshrink = newshrink;
282 b.mark_for_prerender();
286 specialBoxProperties.put("x", new SpecialBoxProperty() {
287 public Object get(Box b) {
288 if (b.surface == null) return new Integer(0);
289 if (b.invisible) return new Integer(0);
290 return new Integer(b.abs(0));
292 public void put(Box b, Object value) {
293 if (b.getParent() == null && b.surface != null) {
294 b.surface.setLocation(stoi(value), b.abs(1));
295 b.surface.centerSurfaceOnRender = false;
297 b.set(abs, 0, stoi(value));
301 specialBoxProperties.put("y", new SpecialBoxProperty() {
302 public Object get(Box b) {
303 if (b.surface == null) return new Integer(0);
304 if (b.invisible) return new Integer(0);
305 return new Integer(b.abs(1));
307 public void put(Box b, Object value) {
308 if (b.getParent() == null && b.surface != null) {
309 b.surface.setLocation(b.abs(0), stoi(value));
310 b.surface.centerSurfaceOnRender = false;
312 b.set(abs, 1, stoi(value));
316 specialBoxProperties.put("width", new SpecialBoxProperty() {
317 public Object get(Box b) { return new Integer(b.size(0)); }
318 public void put(Box b, Object value) {
319 if (b.sizetoimage) return;
320 if (b.getParent() == null && b.surface != null) {
321 b.set(size, 0, Box.max(Surface.scarPicture.getWidth(), stoi(value)));
322 b.mark_for_prerender();
324 b.set(dmax, 0, stoi(value));
325 b.set(dmin, 0, stoi(value));
329 specialBoxProperties.put("height", new SpecialBoxProperty() {
330 public Object get(Box b) { return new Integer(b.size(1)); }
331 public void put(Box b, Object value) {
332 if (b.sizetoimage) return;
333 if (b.getParent() == null && b.surface != null) {
334 b.set(size, 1, Box.max(Surface.scarPicture.getHeight(), stoi(value)));
335 b.mark_for_prerender();
337 b.set(dmax, 1, stoi(value));
338 b.set(dmin, 1, stoi(value));
342 specialBoxProperties.put("flex", new SpecialBoxProperty() {
343 public Object get(Box b) { return new Double(b.flex); }
344 public void put(Box b, Object value) {
345 if (value == null) return;
346 int newflex = stoi(value);
347 if (newflex == b.flex) return;
349 b.mark_for_prerender();
352 specialBoxProperties.put("tile", new SpecialBoxProperty() {
353 public Object get(Box b) { return b.tile ? Boolean.TRUE : Boolean.FALSE; }
354 public void put(Box b, Object value) {
355 boolean newtile = stob(value);
356 if (newtile == b.tile) return;
361 specialBoxProperties.put("align", new SpecialBoxProperty() {
362 public Object get(Box b) {
363 if (b.align == -1) return "topleft";
364 else if (b.align == 1) return "bottomright";
365 else return "center";
367 public void put(Box b, Object value) {
368 String s = value == null ? "" : value.toString();
369 byte newalign = b.align;
370 if (s.equals("topleft")) newalign = -1;
371 else if (s.equals("bottomright")) newalign = 1;
372 else if (s.equals("center")) newalign = 0;
373 else if (Log.on) Log.log(this, "invalid value put to align property: " + value);
374 if (newalign == b.align) return;
376 if (b.getParent() != null) b.getParent().mark_for_prerender();
379 specialBoxProperties.put("invisible", new SpecialBoxProperty() {
380 public Object get(Box b) {
381 for (Box cur = b; cur != null; cur = cur.getParent()) { if (cur.invisible) return Boolean.TRUE; }
382 return Boolean.FALSE;
384 public void put(Box b, Object value) {
385 boolean newinvisible = stob(value);
386 if (newinvisible == b.invisible) return;
387 b.invisible = newinvisible;
388 if (b.getParent() == null) {
389 if (b.surface != null) b.surface.setInvisible(newinvisible);
392 b.getParent().mark_for_prerender();
393 b.getParent().sync_cmin_to_children();
394 b.getParent().dirty(b.pos(0), b.pos(1), b.size(0), b.size(1));
395 b.getParent().dirty(b.oldpos(0), b.oldpos(1), b.oldsize(0), b.oldsize(1));
399 specialBoxProperties.put("absolute", new SpecialBoxProperty() {
400 public Object get(Box b) { return b.absolute ? Boolean.TRUE : Boolean.FALSE; }
401 public void put(Box b, Object value) {
402 boolean newabsolute = stob(value);
403 if (newabsolute == b.absolute) return;
404 b.absolute = newabsolute;
405 if (b.getParent() != null) {
406 b.getParent().mark_for_prerender();
407 b.getParent().sync_cmin_to_children();
411 specialBoxProperties.put("image", new SpecialBoxProperty() {
412 public Object get(Box b) { return b.image == null ? null : Box.imageToNameMap.get(b.image); }
413 public void put(Box b, Object value) { b.setImage(value == null ? null : value.toString()); }
416 specialBoxProperties.put("border", new SpecialBoxProperty() {
417 public Object get(Box b) { return b.border == null ? null : Box.imageToNameMap.get(b.border); }
418 public void put(Box b, Object value) { b.setBorder(value == null ? null : value.toString()); }
421 specialBoxProperties.put("font", new SpecialBoxProperty() {
422 public Object get(Box b) { return b.font; }
423 public void put(Box b, Object value) {
424 b.font = value == null ? null : value.toString();
429 specialBoxProperties.put("globalx", new SpecialBoxProperty() {
430 public Object get(Box b) { return new Integer(b.getParent() == null || b.surface == null ? 0 : b.pos(0)); }
431 public void put(Box b, Object value) {
432 if (b.surface == null || b.getParent() == null) return;
433 b.put("x", new Integer(stoi(value) - stoi(get(b.getParent()))));
437 specialBoxProperties.put("globaly", new SpecialBoxProperty() {
438 public Object get(Box b) { return new Integer(b.getParent() == null || b.surface == null ? 0 : b.pos(1)); }
439 public void put(Box b, Object value) {
440 if (b.surface == null || b.getParent() == null) return;
441 b.put("y", new Integer(stoi(value) - stoi(get(b.getParent()))));
445 specialBoxProperties.put("cursor", new SpecialBoxProperty() {
446 public Object get(Box b) { return b.cursor; }
447 public void put(Box b, Object value) {
448 b.cursor = (String)value;
449 if (b.surface == null) return;
451 // see if we need to update the surface cursor
452 String tempcursor = b.surface.cursor;
453 b.Move(b.surface.mousex, b.surface.mousey, b.surface.mousex, b.surface.mousey);
454 if (b.surface.cursor != tempcursor) b.surface.syncCursor();
458 specialBoxProperties.put("mousex", new SpecialBoxProperty() {
459 public Object get(Box b) { return new Integer(b.surface == null ? 0 : b.surface.mousex - b.pos(0)); }
462 specialBoxProperties.put("mousey", new SpecialBoxProperty() {
463 public Object get(Box b) { return new Integer(b.surface == null ? 0 : b.surface.mousey - b.pos(1)); }
466 specialBoxProperties.put("xwt", new SpecialBoxProperty() {
467 public Object get(Box b) { return XWT.singleton; }
470 specialBoxProperties.put("mouseinside", new SpecialBoxProperty() {
471 public Object get(Box b) { return b.mouseinside ? Boolean.TRUE : Boolean.FALSE; }
474 specialBoxProperties.put("numchildren", new SpecialBoxProperty() {
475 public Object get(Box b) {
476 if (b.redirect == null) return new Integer(0);
477 if (b.redirect != b) return get(b.redirect);
478 return new Integer(b.numChildren());
481 SpecialBoxProperty mouseEventHandler = new SpecialBoxProperty() {
482 public void put(String name, Box b, Object value) {
483 if (b.surface == null) return;
484 for(Box c = b.prevSibling(); c != null; c = c.prevSibling()) {
485 Box siblingChild = c.whoIs(c.surface.mousex, c.surface.mousey);
486 if (siblingChild != null) {
487 siblingChild.put(name, value);
491 if (b.getParent() != null)
492 b.getParent().put(name, value);
495 specialBoxProperties.put("Press1", mouseEventHandler);
496 specialBoxProperties.put("Press2", mouseEventHandler);
497 specialBoxProperties.put("Press3", mouseEventHandler);
498 specialBoxProperties.put("Release1", mouseEventHandler);
499 specialBoxProperties.put("Release2", mouseEventHandler);
500 specialBoxProperties.put("Release3", mouseEventHandler);
501 specialBoxProperties.put("Click1", mouseEventHandler);
502 specialBoxProperties.put("Click2", mouseEventHandler);
503 specialBoxProperties.put("Click3", mouseEventHandler);
504 specialBoxProperties.put("DoubleClick1", mouseEventHandler);
505 specialBoxProperties.put("DoubleClick2", mouseEventHandler);
506 specialBoxProperties.put("DoubleClick3", mouseEventHandler);
508 specialBoxProperties.put("root", new SpecialBoxProperty() {
509 public Object get(Box b) {
510 if (b.surface == null) return null;
511 else if (b.getRoot() == null) return null;
512 else if (b.getParent() == null) return b;
513 else return b.getRoot().getRootProxy();
516 specialBoxProperties.put("Minimized", new SpecialBoxProperty() {
517 public Object get(Box b) {
518 if (b.getParent() == null && b.surface != null) return b.surface.minimized ? Boolean.TRUE : Boolean.FALSE;
521 public void put(Box b, Object value) {
522 if (b.surface == null) return;
523 boolean val = stob(value);
524 if (b.getParent() == null && b.surface.minimized != val) b.surface.setMinimized(val);
528 specialBoxProperties.put("Maximized", new SpecialBoxProperty() {
529 public Object get(Box b) {
530 if (b.getParent() == null && b.surface != null) return b.surface.maximized ? Boolean.TRUE : Boolean.FALSE;
533 public void put(Box b, Object value) {
534 if (b.surface == null) return;
535 boolean val = stob(value);
536 if (b.getParent() == null && b.surface.maximized != val) b.surface.setMaximized(val);
540 specialBoxProperties.put("toback", new SpecialBoxProperty() {
541 public void put(Box b, Object value) {
542 if (b.getParent() == null && stob(value) && b.surface != null) b.surface.toBack();
546 specialBoxProperties.put("tofront", new SpecialBoxProperty() {
547 public void put(Box b, Object value) {
548 if (b.getParent() == null && stob(value) && b.surface != null) b.surface.toFront();
552 specialBoxProperties.put("hscar", new SpecialBoxProperty() {
553 public void put(Box b, Object value) {
554 if (b.getParent() == null && b.surface != null) {
555 b.surface.hscar = stoi(value);
556 b.surface.dirty(0, 0, b.surface.width, b.surface.height);
562 specialBoxProperties.put("vscar", new SpecialBoxProperty() {
563 public void put(Box b, Object value) {
564 if (b.getParent() == null && b.surface != null) {
565 b.surface.vscar = stoi(value);
566 b.surface.dirty(0, 0, b.surface.width, b.surface.height);
572 specialBoxProperties.put("Close", new SpecialBoxProperty() {
573 public void put(Box b, Object value) {
574 if (b.getParent() == null && b.surface != null) b.surface.dispose(true);
578 // these are all do-nothings; just to prevent space from getting taken up in the params Hash.
579 specialBoxProperties.put("KeyPressed", new SpecialBoxProperty());
580 specialBoxProperties.put("KeyReleased", new SpecialBoxProperty());
581 specialBoxProperties.put("PosChange", new SpecialBoxProperty());
582 specialBoxProperties.put("SizeChange", new SpecialBoxProperty());
584 specialBoxProperties.put("hpad", new SpecialBoxProperty() {
585 public Object get(Box b) {
586 if (b.redirect == null) return new Integer(0);
587 if (b.redirect != b) return get(b.redirect);
588 return new Integer(b.pad(0));
590 public void put(Box b, Object value) {
591 if (b.redirect == null) return;
592 if (b.redirect != b) { put(b.redirect, value); return; }
593 int newval = stoi(value);
594 if (newval == b.pad(0)) return;
595 b.set(pad, 0, newval);
599 specialBoxProperties.put("vpad", new SpecialBoxProperty() {
600 public Object get(Box b) {
601 if (b.redirect == null) return new Integer(0);
602 if (b.redirect != b) return get(b.redirect);
603 return new Integer(b.pad(1));
605 public void put(Box b, Object value) {
606 if (b.redirect == null) return;
607 if (b.redirect != b) { put(b.redirect, value); return; }
608 int newval = stoi(value);
609 if (newval == b.pad(1)) return;
610 b.set(pad, 1, newval);
614 specialBoxProperties.put("indexof", new SpecialBoxProperty() {
615 public Object get(Box b) { return b.indexof(); }
618 specialBoxProperties.put("minwidth", new SpecialBoxProperty() {
619 public Object get(Box b) { return new Integer(b.dmin(0)); }
620 public void put(Box b, Object value) {
621 if (b.sizetoimage) return;
622 b.set(dmin, 0, stoi(value));
626 specialBoxProperties.put("maxwidth", new SpecialBoxProperty() {
627 public Object get(Box b) { return new Integer(b.dmax(0)); }
628 public void put(Box b, Object value) {
629 if (b.sizetoimage) return;
630 b.set(dmax, 0, stoi(value));
634 specialBoxProperties.put("minheight", new SpecialBoxProperty() {
635 public Object get(Box b) { return new Integer(b.dmin(1)); }
636 public void put(Box b, Object value) {
637 if (b.sizetoimage) return;
638 b.set(dmin, 1, stoi(value));
642 specialBoxProperties.put("maxheight", new SpecialBoxProperty() {
643 public Object get(Box b) { return new Integer(b.dmax(1)); }
644 public void put(Box b, Object value) {
645 if (b.sizetoimage) return;
646 b.set(dmax, 1, stoi(value));
650 specialBoxProperties.put("redirect", new SpecialBoxProperty() {
651 public void put(Box b, Object value) { }
652 public Object get(Box b) {
653 if (b.redirect == null) return null;
654 if (b.redirect == b) return Boolean.TRUE;
655 return get(b.redirect);
659 specialBoxProperties.put("apply", new SpecialBoxProperty() {
660 public void put(Box b, Object value) { }
661 public Object get(final Box b) { return new JS.Callable() {
662 public Object call(JS.Array args) throws JS.Exn {
663 if (args.elementAt(0) instanceof String) {
664 String templatename = (String)args.elementAt(0);
665 Template t = Template.getTemplate(templatename, null);
667 if (Log.on) Log.logJS(this, "template " + templatename + " not found");
669 if (ThreadMessage.suspendThread()) try {
670 JS.Callable callback = args.length() < 2 ? null : (Callable)args.elementAt(1);
671 t.apply(b, null, null, callback, 0, t.numUnits());
673 ThreadMessage.resumeThread();
677 } else if (args.elementAt(0) instanceof JS && !(args.elementAt(0) instanceof Box)) {
678 JS s = (JS)args.elementAt(0);
679 Object[] keys = s.keys();
680 for(int j=0; j<keys.length; j++) b.put(keys[j].toString(), s.get(keys[j]));
686 specialBoxProperties.put("id", new SpecialBoxProperty() {
687 public void put(Box b, Object value) { }
688 public Object get(Box b) { return b.id; }
693 /** helper that converts a String to a boolean according to JavaScript coercion rules */
694 public static boolean stob(Object o) {
695 if (o == null) return false;
696 return Boolean.TRUE.equals(o) || "true".equals(o);
699 /** helper that converts a String to an int according to JavaScript coercion rules */
700 public static int stoi(Object o) {
701 if (o == null) return 0;
702 if (o instanceof Integer) return ((Integer)o).intValue();
705 if (!(o instanceof String)) s = o.toString();
708 try { return Integer.parseInt(s.indexOf('.') == -1 ? s : s.substring(0, s.indexOf('.'))); }
709 catch (NumberFormatException e) { return 0; }