Files
gzz-mirror/Java/flob/RankTextView.zob
2026-09-14 20:19:29 -04:00

308 lines
7.9 KiB
Java

/*
VStreamRaster.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 raster of flowing text.
* The FlobRaster is implemented mostly for testing purposes - this class
* would mostly be called from another raster.
*/
public class RankTextView implements FlobView, ZOb {
public static final String rcsid = "$Id$";
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); }
STRUCTPARAMS {
/** The width of the flowing text at maximum. Negative value
means that the width of the window should be used. */
int width
= 300;
/** The font for the maximal line. */
ScalableFont font
= new ScalableFont("SansSerif", Font.PLAIN, 16);
/** The half-width of the bulge. */
int bulge
= 10;
/** Whether to show cuts. */
boolean cuts
= true;
/** Which dimension to use. */
String dim
= "d.2";
/** Whether to billow the text. */
boolean billow
= true;
/** Whether to show XOR cursors. */
boolean xor
= true;
/** The backround colour for all flobs (or null if determined
from the cursors. */
Color bgcolor
= null;
}
protected Font getfont(int scale) {
return font.getFont(scale);
}
protected FontMetrics getfontmet(int scale) {
return font.getFontMetrics(scale);
}
SimpleLineInfo.Layout layb = new LayBillow();
SimpleLineInfo.Layout layf = new LayFlat();
SimpleLineBreaker brk = new SimpleLineBreaker();
protected int getFontScale(int line, boolean doBillow) {
int w = (doBillow ? layb : layf).getWidth(line);
return (1000*w)/width;
}
class LayBillow implements SimpleLineInfo.Layout {
public final FontMetrics getFontMetrics(int line) {
return getfontmet(getFontScale(line, true));
}
public final int getWidth(int line) {
if(bulge <= 0) return width;
float bfunc = (float)(
1.0/ ( 1 + (line * (float)line) / (bulge * bulge) ) );
return (int)(bfunc * width);
}
public final int getCenterLine() {
return 0;
}
}
class LayFlat implements SimpleLineInfo.Layout {
public final FontMetrics getFontMetrics(int line) {
return getfontmet(1000);
}
public final int getWidth(int line) {
return width;
}
public final int getCenterLine() {
return 0;
}
}
/** Raster an area.
* Returns a bounding rectangle for the text plotted.
*/
public Rectangle raster(FlobSet into, ZZCell c, int offs, boolean doBillow,
int startx, int starty, int xormode) {
if (width < 0) width = into.getSize().width;
Rectangle res = new Rectangle();
// read the whole string first
int soffs = -1;
StringBuffer s = new StringBuffer();
ZZCell head = c.h(dim, -1);
boolean first = true;
for(ZZCell h = head;
h != null && (first || h!=head); h = h.s(dim, 1)) {
first = false;
if(h == c)
soffs = offs + s.length();
s.append(h.getText());
}
if(soffs < 0)
throw new ZZError("??? ARGH");
String txt = s.toString();
SimpleLineInfo sli = new SimpleLineInfo(txt, soffs,
(doBillow?layb:layf));
int[] linestops = brk.breakLines(sli);
p("Breaklines: "+offs);
for(int i=0; i<linestops.length; i++)
p("Line: "+linestops[i]);
for(int i=-10; i<=10; i++) {
p("WFM: "+layb.getWidth(i)+" "+getFontScale(i, doBillow));
}
int ctr = - linestops[0];
/** Current Y offset for the loop. */
int cury = starty;
// Calculate the starting Y coordinate
for(int i = ctr; i>=0; i--) {
cury -= getfontmet(getFontScale(i-ctr, doBillow)).getHeight();
}
res.x = startx; res.width = width;
res.y = cury;
// Downwards from center.
// start-splitcellflob needs very careful attention.
/** Current offset in the whole string.
*/
int curoffs = 0;
/** Current line.
*/
int curline = 0;
/** Current X-coordinate.
*/
int curx = startx;
int fi = getFontScale(curline - ctr, doBillow);
Font f = getfont(fi);
FontMetrics fm = getfontmet(fi);
SplitCellFlob1 latest = null;
first = true;
for(ZZCell h = head;
h != null && (first || h != head); h = h.s(dim, 1)) {
first = false;
final String st = h.getText();
final int len = st.length();
int nth = 0;
SplitCellFlob1 parent = null;
// Find the cursors on this cell. Only one is shown.
int curs = ZZCursorReal.NO_OFFSET;
ZZCell ccurs = h;
while((ccurs = ccurs.s("d.cursor", 1))!=null) {
curs = ZZCursorReal.getOffs(ccurs);
if(curs != ZZCursorReal.NO_OFFSET) break;
}
if(h.s("d.cut", 1) != null) {
// There was a cut.
into.add(new LineDecor(curx, cury, curx, cury+fm.getHeight(),
Color.red, 1));
}
while(curoffs + len - nth > linestops[curline+1]) {
p("Parent: "+nth+" "+len+" "+curline+" "+linestops[curline+1]);
SplitCellFlob1 cur = new SplitCellFlob1(
curx, cury, 100, fm.stringWidth(st.substring(nth,
nth+
(linestops[curline+1] - curoffs))),
fm.getHeight(), h, f, fm, parent,
nth, linestops[curline+1]-curoffs, xormode, bgcolor);
if(bgcolor == null) cur.showCursor();
cur.setPrev(latest); latest = cur;
if(curs != ZZCursorReal.NO_OFFSET)
addCurs(into, cur, curs);
parent = cur;
into.add(cur);
// Split it.
nth += linestops[curline+1] - curoffs;
curoffs = linestops[curline+1];
curline ++;
cury += fm.getHeight();
curx = startx;
fi = getFontScale(curline - ctr, doBillow);
f = getfont(fi);
fm = getfontmet(fi);
if(curline >= linestops.length - 1) {
p("LAST LINE: ALL OUT");
break;
}
}
if(curline >= linestops.length - 1)
break;
p("Last: "+nth+" "+len+" "+curline+" "+linestops[curline+1]+" "+
st.length());
int w = 0;
String substr = st.substring(nth, len);
p("Substr: "+substr);
SplitCellFlob1 last = new SplitCellFlob1(
curx, cury, 100,
(w = fm.stringWidth(substr)),
fm.getHeight(), h, f, fm, parent, nth, len-nth, xormode, bgcolor);
if(bgcolor == null) last.showCursor();
last.setPrev(latest); latest = last;
if(curs != ZZCursorReal.NO_OFFSET)
addCurs(into, last, curs);
curoffs += len-nth;
curx += w;
into.add(last);
}
p("FINISHED");
res.height = cury - res.y + fm.getHeight();
return res;
}
public Rectangle raster(FlobSet into, ZZCell c, int offs, boolean doBillow,
int startx, int starty) {
return raster(into, c, offs, doBillow, startx, starty,
SplitCellFlob1.XOR_NO);
}
private void addCurs(FlobSet into, SplitCellFlob1 sf, int ind) {
if(!(ind >= sf.start && ind <= sf.start + sf.n))
return;
int x = sf.getStrX(ind);
if(x >= 0)
into.add(new LineDecor(x, sf.y, x, sf.y+sf.h,
Color.black, sf.d));
}
public void raster(FlobSet into, FlobFactory fact,
ZZCell view, String[] dims, ZZCell accursed) {
ZZCell c = ZZCursorReal.get(view);
int offs = ZZCursorReal.getOffs(view);
int xormode = SplitCellFlob1.XOR_LINE;
if(offs == ZZCursor.NO_OFFSET) {
offs = 0;
xormode = SplitCellFlob1.XOR_SOLID;
}
if(!xor) xormode = SplitCellFlob1.XOR_NO;
Dimension d = into.getSize();
int cy = d.height / 2;
raster(into, c, offs, billow, 0, cy, xormode);
}
// public VStreamRaster() { }
}
// vim: set syntax=java :