*
* <p>The rendering process consists of four phases; each requires
* one DFS pass over the tree</p>
- * <ol><li> <b>repacking</b>: children of a box are packed into columns
- * and rows according to their colspan/rowspan attributes and
- * ordering.
- * <ol><li> <b>reconstraining</b>: Minimum and maximum sizes of columns are computed.
- * <li> <b>resizing</b>: width/height and x/y positions of children
- * are assigned, and PosChange/SizeChanges are triggered.
- * <li> <b>repainting</b>: children draw their content onto the PixelBuffer.
+ * <ol><li> <b>pack()</b>: each box sets its childrens' row/col
+ * <ol><li> <b>constrain()</b>: contentwidth is computed
+ * <li> <b>resize()</b>: width/height and x/y positions are set
+ * <li> <b>render()</b>: children draw their content onto the PixelBuffer.
* </ol>
*
- * The first three passes together are called the <i>reflow</i> phase.
- * Reflowing is done in a seperate pass since PosChanges and
- * SizeChanges trigger an Surface.abort; if rendering were done in the same
- * pass, rendering work done prior to the Surface.abort would be wasted.
+ * The first three passes together are called the <i>reflow</i>
+ * phase. Reflowing is done in a seperate pass since SizeChanges
+ * trigger a Surface.abort; if rendering were done in the same pass,
+ * rendering work done prior to the Surface.abort would be wasted.
*/
public final class Box extends JSScope implements Scheduler.Task {
// Macros //////////////////////////////////////////////////////////////////////
- //#define LENGTH int
-
final void REPLACE() { for(Box b2 = this; b2 != null && !b2.test(REPLACE); b2 = b2.parent) b2.set(REPLACE); }
final void RECONSTRAIN() { for(Box b2 = this; b2 != null && !b2.test(RECONSTRAIN); b2 = b2.parent) b2.set(RECONSTRAIN); }
final void REPACK() { for(Box b2 = this; b2 != null && !b2.test(REPACK); b2 = b2.parent) b2.set(REPACK); }
protected Box() { super(null); }
static Hash boxToCursor = new Hash(500, 3); // FIXME memory leak
- public static final int MAX_LENGTH = Integer.MAX_VALUE;
- static final Font DEFAULT_FONT;
-
- static {
- Font f = null;
- try { f = Font.getFont((Stream)Main.builtin.get("fonts/vera/Vera.ttf"), 10); }
- catch(JSExn e) { Log.info(Box.class, "should never happen: "+e); }
- DEFAULT_FONT = f;
- }
+ static final Font DEFAULT_FONT = Font.getFont((Stream)Main.builtin.get("fonts/vera/Vera.ttf"), 10);
// FIXME update these
// events can have write traps, but not read traps
private int aspect = 0;
// specified directly by user
- public LENGTH minwidth = 0;
- public LENGTH maxwidth = MAX_LENGTH;
- public LENGTH minheight = 0;
- public LENGTH maxheight = MAX_LENGTH;
+ public int minwidth = 0;
+ public int maxwidth = Integer.MAX_VALUE;
+ public int minheight = 0;
+ public int maxheight = Integer.MAX_VALUE;
private short rows = 1;
private short cols = 0;
private short rowspan = 1;
// computed during reflow
private short row = 0;
private short col = 0;
- public LENGTH x = 0;
- public LENGTH y = 0;
- public LENGTH ax = 0; // FEATURE: roll these into x/y; requires lots of changes
- public LENGTH ay = 0; // FEATURE: roll these into x/y; requires lots of changes; perhaps y()?
- public LENGTH width = 0;
- public LENGTH height = 0;
- private LENGTH contentwidth = 0; // == max(minwidth, textwidth, sum(child.contentwidth))
- private LENGTH contentheight = 0;
+ public int x = 0;
+ public int y = 0;
+ public int ax = 0; // FEATURE: roll these into x/y; requires lots of changes
+ public int ay = 0; // FEATURE: roll these into x/y; requires lots of changes; perhaps y()?
+ public int width = 0;
+ public int height = 0;
+ private int contentwidth = 0; // == max(minwidth, textwidth, sum(child.contentwidth))
+ private int contentheight = 0;
/*
private VectorGraphics.VectorPath path = null;
set(REPLACE); // FIXME: be smarter / more incremental
}
- void resize(LENGTH x, LENGTH y, LENGTH width, LENGTH height) {
+ void resize(int x, int y, int width, int height) {
if (x == this.x && y == this.y && width == this.width && height == this.height) return;
boolean sizechange = (this.width != width || this.height != height) && getTrap("SizeChange") != null;
int thisx = parent == null ? 0 : this.x;
public static class NotCacheableException extends Exception { }
// streams are "sealed" by default to prevent accidental object leakage
- public void put(Object key, Object val) throws JSExn { }
+ public void put(Object key, Object val) { }
private Cache getCache = new Cache(100);
- protected Object _get(Object key) throws JSExn { return null; }
- public final Object get(Object key) throws JSExn {
+ protected Object _get(Object key) { return null; }
+ public final Object get(Object key) {
Object ret = getCache.get(key);
if (ret == null) getCache.put(key, ret = _get(key));
return ret;
private String url;
public String toString() { return "Stream.HTTP:" + url; }
HTTP(String url) { while (url.endsWith("/")) url = url.substring(0, url.length() - 1); this.url = url; }
- public Object _get(Object key) throws JSExn { return new HTTP(url + "/" + (String)key); }
+ public Object _get(Object key) { return new HTTP(url + "/" + (String)key); }
public String getCacheKey(Vec path) throws NotCacheableException { return url; }
public InputStream getInputStream() throws IOException { return new org.ibex.HTTP(url).GET(); }
}
public String toString() { return "file:" + path; }
public String getCacheKey() throws NotCacheableException { throw new NotCacheableException(); /* already on disk */ }
public InputStream getInputStream() throws IOException { return new FileInputStream(path); }
- public Object _get(Object key) throws JSExn { return new File(path + java.io.File.separatorChar + (String)key); }
+ public Object _get(Object key) { return new File(path + java.io.File.separatorChar + (String)key); }
}
/** "unwrap" a Zip archive */
this.path = path;
}
public String getCacheKey() throws NotCacheableException { return parent.getCacheKey() + "!zip:"; }
- public Object _get(Object key) throws JSExn { return new Zip(parent, path==null?(String)key:path+'/'+(String)key); }
+ public Object _get(Object key) { return new Zip(parent, path==null?(String)key:path+'/'+(String)key); }
public InputStream getInputStream() throws IOException {
InputStream pis = parent.getInputStream();
ZipInputStream zis = new ZipInputStream(pis);
Cab(Stream parent) { this(parent, null); }
Cab(Stream parent, String path) { this.parent = parent; this.path = path; }
public String getCacheKey() throws NotCacheableException { return parent.getCacheKey() + "!cab:"; }
- public Object _get(Object key) throws JSExn { return new Cab(parent, path==null?(String)key:path+'/'+(String)key); }
+ public Object _get(Object key) { return new Cab(parent, path==null?(String)key:path+'/'+(String)key); }
public InputStream getInputStream() throws IOException { return new MSPack(parent.getInputStream()).getInputStream(path); }
}