/* VanishingView.zob * * Copyright (c) 1999-2000, Ted Nelson and Tuomas Lukka * * You may use and distribute under the terms of either the GNU Lesser * General Public License, either version 2 of the license or, * at your choice, any later version. Alternatively, you may use and * distribute under the terms of the XPL. * * See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of * the licenses. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the README * file for more details. * */ /* * Written by Tuomas Lukka */ package org.gzigzag; import java.awt.*; import java.awt.event.*; import java.util.*; /** A reimplementation of the vanishing raster. * Much simpler than the original one since this one does not try * to do the hard rasters as well. */ public class VanishingView implements FlobView, ZOb { public static final String rcsid = "$Id: VanishingView.zob,v 1.9 2000/12/11 02:54:44 tjl Exp $"; public static boolean dbg = false; static final void p(String s) { if(dbg) System.out.println(s); } static final void pa(String s) { System.out.println(s); } // Following are the parameters out of which the constructor // is created. STRUCTPARAMS { /** The factor to shrink the cells with when moving away from * center. */ float[] shrink // 2..2 = new float[] {(float)0.9, (float)0.9}; /** The factor the center cell is enlarged with from default. */ float[] initmul // 2..2 = new float[] {(float)1.6, (float)1.6}; /** The factor to enlarge the center cell on top of initmul. * This only has an effect on the center cell whereas initmul * affects all cells. */ float[] centermul // 2..2 = new float[] {(float)1.0, (float)1.0}; /** The distance between neighbouring cells. */ int[] gap // 2..2 = new int[] {5, 5}; /** The depth to raster to. */ int depth = 5; /** The precedence order of dimensions. */ int[] pref // 2..5 = new int[] {0, 1, 2}; /** Whether to allow cell sizes to vary. */ boolean varsize = false; /** Whether alignment around visual flob center is to be used. * If true, halign is ignored. */ boolean centeralign = true; /** Distance reverse perspective. */ float revper = (float)1.00; /** Horizontal alignment. * 0 = center, -1 = left, 1 = right. */ int halign = 0; } // XXX This should be a structparam later on. FlobDecorator linker = new StdLinks(); // Offsets of x and y static int[] xoffs = new int[] {1, 0, 1}; static int[] yoffs = new int[] {0, 1, 1}; public void raster(FlobSet into, FlobFactory fact, ZZCell view, String[] dims, ZZCell accursed) { Dimension fs = into.getSize(); // Precalculate sizes and gaps. int[] xgap = new int[depth]; int[] ygap = new int[depth]; int[] xsize = new int[depth+1]; int[] ysize = new int[depth+1]; float[] sizfact = new float[depth+1]; float xf = initmul[0]; float yf = initmul[1]; Dimension d0 = fact.getSize(null, yf); Dimension d = (varsize ? fact.getSize(accursed, yf) : d0); xsize[0] = d.width; ysize[0] = d.height; sizfact[0] = yf; float yf0 = yf, xf0=xf; for(int i=0; i= maxd) continue; if(did[dim].get(curFlob[0].c) != null) continue; did[dim].put(curFlob[0].c, curFlob[0].c); // Current depth int curd = (curFlob[0].d - d1) / dm; ZZIter.NEnum rank = ZZIter.alternate(curFlob[0].c, false, dims[pref[dim]], 1); ZZCell next; while((next = rank.nextCell()) != null) { int curind = (rank.nth() < 0 ? 0 : 1); int dir = curind * 2 - 1; int xdep = (rank.nth() < 0 ? -rank.nth() : rank.nth()); Flob f = curFlob[curind]; if(cellsDone.get(next) != null || curd + xdep >= depth) { rank.stop(); continue; } cellsDone.put(next, next); if(centeralign) { // First, determine alignment. int xalign = dir * xoffs[pref[dim]]; int yalign = dir * yoffs[pref[dim]]; // Then, find alignment point in last cell, // centered on center of screen f.getPoint(aligned, xalign, yalign); // Using that, find alignment point // in the next cell. aligned.x -= fs.width / 2; aligned.x *= revper; aligned.x += fs.width / 2; aligned.y -= fs.height / 2; aligned.y *= revper; aligned.y += fs.height / 2; aligned.x += xalign*xgap[curd+xdep-1]; aligned.y += yalign*ygap[curd+xdep-1]; Dimension size = new Dimension(xsize[curd+xdep], ysize[curd+xdep]); f = curFlob[curind] = fact.centerFlob(into, next, next, sizfact[curd+xdep], aligned, -xalign, -yalign, d1 + dm * (curd + xdep), varsize ? null : size); } else { int x=0, y=0, w=0, h=0; if(varsize) { Dimension dvar = fact.getSize(next, sizfact[curd+xdep]); w = dvar.width; h = dvar.height; } else { w = xsize[curd+xdep]; h = ysize[curd+xdep]; } // A bit tricky due to flob coords being // UL corner. // First, find alignment point in last cell, // centered on center of screen int alignedX = f.x + (halign+1)*f.w/2 - fs.width/2; int alignedY = f.y + f.h/2 - fs.height/2; // Then, using that, find alignment point // in the next cell. int xof = xoffs[pref[dim]]; alignedX += dir * xof * ( xgap[curd+xdep-1] + (1-dir*halign) * f.w/2 + (1+dir*halign) * w/2 ); alignedY += dir * yoffs[pref[dim]] * ( ygap[curd+xdep-1] + f.h/2 + h/2 ); // Expand the coordinate system around the // origin alignedX *= revper; alignedY *= revper; // Finally, find upper left corner of next cell. x = alignedX - (halign+1)*w/2 + fs.width/2; y = alignedY - h/2 + fs.height/2; p("Vanishing: puttig "+next+ x+" "+y+" "+w+" "+h); f = curFlob[curind] = fact.makeFlob(into, next, next, sizfact[curd+xdep], x, y, d1 + dm * (curd + xdep), w, h); } cur.addElement(f); did[dim].put(f.c, f.c); added = true; } } // If we added cells, and we're not doing a hard // raster, start doing dimensions all over again. if(added) dim = -1; } linker.decorate(into, "", view); // Do the dimensions. if(true) ZZUtil.showFlobDims(into, fact, view, 3); } } // vim: set syntax=java :