312 lines
8.7 KiB
Plaintext
312 lines
8.7 KiB
Plaintext
|
|
/*
|
||
|
|
Nile1View.java
|
||
|
|
*
|
||
|
|
* Copyright (c) 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.module;
|
||
|
|
import org.gzigzag.*;
|
||
|
|
import java.util.*;
|
||
|
|
import java.awt.*;
|
||
|
|
import java.io.*;
|
||
|
|
|
||
|
|
/** A view for nile streams.
|
||
|
|
*/
|
||
|
|
|
||
|
|
public class Nile1View implements FlobView, ZOb {
|
||
|
|
public static final String rcsid = "$Id: Nile1View.zob,v 1.4 2001/01/26 13:53:27 ajk Exp $";
|
||
|
|
public static boolean dbg = false;
|
||
|
|
static void p(String s) { if(dbg) System.out.println(s); }
|
||
|
|
static void pa(String s) { System.out.println(s); }
|
||
|
|
|
||
|
|
|
||
|
|
STRUCTPARAMS {
|
||
|
|
/** The default font to use.
|
||
|
|
*/
|
||
|
|
Font font
|
||
|
|
= new Font("SansSerif", Font.PLAIN, 11);
|
||
|
|
|
||
|
|
/** The distance between paragraphs.
|
||
|
|
*/
|
||
|
|
int paraskip
|
||
|
|
= 8;
|
||
|
|
|
||
|
|
/** The left-side margin for normal text.
|
||
|
|
* Headings hang left of this margin.
|
||
|
|
*/
|
||
|
|
int lmargin
|
||
|
|
= 50;
|
||
|
|
|
||
|
|
ZOb ftextlayouter
|
||
|
|
= new FTextLayouter();
|
||
|
|
|
||
|
|
/** Whether to use a special color for span (transcluded) cells. */
|
||
|
|
boolean showcopy
|
||
|
|
= false;
|
||
|
|
}
|
||
|
|
|
||
|
|
/** Bold and italic derivatives of the font given.
|
||
|
|
* The first index is the level of the text i.e.
|
||
|
|
* from paragraph to H1.
|
||
|
|
*/
|
||
|
|
Font[][][] bifonts;
|
||
|
|
FontMetrics[][][] bifontms;
|
||
|
|
|
||
|
|
INITIALIZE {
|
||
|
|
bifonts = new Font[7][2][2];
|
||
|
|
bifontms = new FontMetrics[7][2][2];
|
||
|
|
for(int l = 0; l < bifonts.length; l++) {
|
||
|
|
int size = font.getSize();
|
||
|
|
if(l > 0 && l < 5) size += l-1;
|
||
|
|
if(l == 5) size += 6;
|
||
|
|
if(l == 6) size += 9;
|
||
|
|
bifonts[l][1][0] = new Font(font.getName(),
|
||
|
|
Font.BOLD, size);
|
||
|
|
bifonts[l][1][1] = new Font(font.getName(),
|
||
|
|
Font.BOLD | Font.ITALIC, size);
|
||
|
|
|
||
|
|
if(l == 0) {
|
||
|
|
bifonts[l][0][0] = new Font(font.getName(), 0, size);
|
||
|
|
bifonts[l][0][1] = new Font(font.getName(),
|
||
|
|
Font.ITALIC, size);
|
||
|
|
} else { // All bold for headers
|
||
|
|
bifonts[l][0][0] = bifonts[l][1][0];
|
||
|
|
bifonts[l][0][1] = bifonts[l][1][1];
|
||
|
|
}
|
||
|
|
for(int b = 0; b<2; b++)
|
||
|
|
for(int i = 0; i<2; i++)
|
||
|
|
bifontms[l][b][i] = FONTMETRICS(bifonts[l][b][i]);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
Color selcolor = Color.white;
|
||
|
|
Color copycolor = Color.yellow.darker().darker().darker().darker();
|
||
|
|
|
||
|
|
/** Return the formatted text object for one paragraph.
|
||
|
|
*/
|
||
|
|
FText paragraph(ZZCell start, ZZCell endBefore, ZZCursor offsetOfC,
|
||
|
|
int[]into,
|
||
|
|
ZZCursor selectEnd)
|
||
|
|
{
|
||
|
|
p("Paragraph! "+start+" "+endBefore+" ");
|
||
|
|
ZZCell selsc = null;
|
||
|
|
int selso = 0;
|
||
|
|
if(offsetOfC != null) {
|
||
|
|
selsc = offsetOfC.get();
|
||
|
|
selso = offsetOfC.getOffs();
|
||
|
|
}
|
||
|
|
ZZCell offsetOf = selsc;
|
||
|
|
ZZCell selec = null;
|
||
|
|
int seleo = 0;
|
||
|
|
if(selectEnd != null) {
|
||
|
|
selec = selectEnd.get();
|
||
|
|
seleo = selectEnd.getOffs();
|
||
|
|
}
|
||
|
|
boolean selected = (selsc == null && selec != null);
|
||
|
|
|
||
|
|
if(selso == ZZCursor.NO_OFFSET || selec == null) {
|
||
|
|
selsc = null;
|
||
|
|
selec = null;
|
||
|
|
selected = false;
|
||
|
|
}
|
||
|
|
|
||
|
|
FText.Part part = null;
|
||
|
|
|
||
|
|
int level = Nile2Iter.getLevel(start);
|
||
|
|
int curOffs = 0;
|
||
|
|
int b = 0, i = 0;
|
||
|
|
Vector parts = new Vector();
|
||
|
|
LoopDetector ld = new LoopDetector();
|
||
|
|
LoopDetector ld2 = new LoopDetector();
|
||
|
|
for(ZZCell c = start; c != null && c != endBefore; c = c.s("d.nile")) {
|
||
|
|
ld.detect(c);
|
||
|
|
for(ZZCell fs = c.s("d.nile-fmt-start"); fs != null;
|
||
|
|
fs = fs.s("d.nile-fmt-start")) {
|
||
|
|
ld.detect(fs);
|
||
|
|
if(fs.getText().equals("B")) b++;
|
||
|
|
else if(fs.getText().equals("I")) i++;
|
||
|
|
else p("Invalid format: "+fs.getText());
|
||
|
|
}
|
||
|
|
int b0 = (b > 0 ? 1 : 0);
|
||
|
|
int i0 = (i > 0 ? 1 : 0);
|
||
|
|
int len = c.getText().length();
|
||
|
|
|
||
|
|
if(c == offsetOf && into != null) into[0] = curOffs;
|
||
|
|
int internoffs = 0;
|
||
|
|
if(c == selsc) {
|
||
|
|
if(selso > len) {
|
||
|
|
ZZLogger.log("Warning: start over length "+selso+" "+len);
|
||
|
|
selso = len;
|
||
|
|
}
|
||
|
|
part = new FText.CellPart( c, 0, selso,
|
||
|
|
bifonts[level][b0][i0], bifontms[level][b0][i0],
|
||
|
|
null, c.getSpan() == null ? null : copycolor);
|
||
|
|
parts.addElement(part);
|
||
|
|
internoffs = selso;
|
||
|
|
selected = true;
|
||
|
|
p("Start selection: "+selso+" "+selsc);
|
||
|
|
}
|
||
|
|
if(c == selec && seleo >= internoffs) {
|
||
|
|
if(seleo > len) {
|
||
|
|
ZZLogger.log("Warning: end over length "+seleo+" "+len);
|
||
|
|
seleo = len;
|
||
|
|
}
|
||
|
|
part = new FText.CellPart( c, internoffs, seleo-internoffs,
|
||
|
|
bifonts[level][b0][i0], bifontms[level][b0][i0],
|
||
|
|
selcolor, c.getSpan() == null ? null : copycolor);
|
||
|
|
parts.addElement(part);
|
||
|
|
internoffs = seleo;
|
||
|
|
selected = false;
|
||
|
|
selectEnd.set((ZZCell)null);
|
||
|
|
p("End selection: "+seleo+" "+selec);
|
||
|
|
}
|
||
|
|
|
||
|
|
part = new FText.CellPart( c, internoffs, len-internoffs,
|
||
|
|
bifonts[level][b0][i0], bifontms[level][b0][i0],
|
||
|
|
selected ? selcolor : null,
|
||
|
|
c.getSpan() == null ? null : copycolor);
|
||
|
|
|
||
|
|
parts.addElement(part);
|
||
|
|
curOffs += len;
|
||
|
|
|
||
|
|
for(ZZCell fe = c.s("d.nile-fmt-end"); fe != null;
|
||
|
|
fe = fe.s("d.nile-fmt-start")) {
|
||
|
|
ld2.detect(fe); // Can't use same: same cell is start&end
|
||
|
|
if(fe.getText().equals("B")) b--;
|
||
|
|
else if(fe.getText().equals("I")) i--;
|
||
|
|
else p("Invalid format: "+fe.getText());
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return new FText(parts);
|
||
|
|
}
|
||
|
|
|
||
|
|
Rectangle pmarg(Rectangle r, ZZCell para) {
|
||
|
|
int level = Nile2Iter.getLevel(para);
|
||
|
|
Rectangle ret = new Rectangle(r);
|
||
|
|
int w = (6 - level) * lmargin / 6;
|
||
|
|
ret.x += w; ret.width -= w;
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
|
||
|
|
boolean[] beginningSentence = new boolean[2];
|
||
|
|
public Rectangle placeParagraph(FlobSet into,
|
||
|
|
FText ft, ZZCell para,Rectangle origrect,
|
||
|
|
int direction, int initY, int middleOffs) {
|
||
|
|
beginningSentence[0] = true;
|
||
|
|
beginningSentence[1] = false;
|
||
|
|
// Margins.
|
||
|
|
Rectangle rect = pmarg(origrect, para);
|
||
|
|
Rectangle ret = ((FTextLayouter)ftextlayouter).place(into, ft, rect,
|
||
|
|
1,
|
||
|
|
direction, initY, middleOffs, false,
|
||
|
|
beginningSentence);
|
||
|
|
// Now, do the cool thing with the section headings: include
|
||
|
|
// previous and next section headings of the same level here.
|
||
|
|
if(Nile2Iter.getLevel(para) > 0) {
|
||
|
|
|
||
|
|
ZZCell strcell = para.s("d.nile-struct");
|
||
|
|
if(strcell == null) return ret;
|
||
|
|
|
||
|
|
for(int dir = -1; dir <= 1; dir += 2) {
|
||
|
|
ZZCell prevsec = strcell.s("nile1str:breadth",dir);
|
||
|
|
if(prevsec == null) continue;
|
||
|
|
prevsec = prevsec.h("nile1str:depth").s("d.nile-struct", -1);
|
||
|
|
if(prevsec == null) continue;
|
||
|
|
beginningSentence[0] = true;
|
||
|
|
beginningSentence[1] = false;
|
||
|
|
FText nft = paragraph(prevsec, Nile2Iter.findStruct(prevsec, 1, false),
|
||
|
|
null, null, null);
|
||
|
|
((FTextLayouter)ftextlayouter).place(into, nft, rect, 200,
|
||
|
|
dir, ret.y + (dir < 0 ? 0 : ret.height),
|
||
|
|
0, false, beginningSentence);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
public void raster(FlobSet into, FlobFactory fact,
|
||
|
|
ZZCell view, String[] dims, ZZCell accursed) {
|
||
|
|
int[] offs = new int[1];
|
||
|
|
|
||
|
|
LoopDetector ld = new LoopDetector();
|
||
|
|
|
||
|
|
ZZCursor selectEnd = null;
|
||
|
|
ZZCell sele = view.s("d.nile-sel");
|
||
|
|
if(sele != null) {
|
||
|
|
selectEnd = ZZCursorVirtual.createFromReal(sele);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Do the center paragraph first.
|
||
|
|
ZZCell firstpara = Nile2Iter.findStruct(accursed, -1, true);
|
||
|
|
ZZCell nextpara = Nile2Iter.findStruct(accursed, 1, false);
|
||
|
|
|
||
|
|
FText ft = paragraph(firstpara, nextpara, new ZZCursorReal(view),
|
||
|
|
offs, selectEnd);
|
||
|
|
|
||
|
|
Dimension size = into.getSize();
|
||
|
|
Rectangle rect = new Rectangle(0, 0, size.width, size.height);
|
||
|
|
|
||
|
|
Rectangle ctr = placeParagraph(into, ft, firstpara, rect,
|
||
|
|
0, rect.y+rect.height/2,
|
||
|
|
ZZCursorReal.getVisualTextOffset(view));
|
||
|
|
|
||
|
|
// Go into positive direction.
|
||
|
|
Rectangle r = ctr;
|
||
|
|
while(nextpara != null) {
|
||
|
|
ld.detect(nextpara);
|
||
|
|
ZZCell next = Nile2Iter.findStruct(nextpara, 1, false);
|
||
|
|
ft = paragraph(nextpara, next, null, null, selectEnd);
|
||
|
|
|
||
|
|
r = placeParagraph(into, ft, nextpara, rect,
|
||
|
|
1, r.y+r.height + paraskip, 0);
|
||
|
|
|
||
|
|
nextpara = next;
|
||
|
|
|
||
|
|
if(r.y + r.height > size.height) break;
|
||
|
|
}
|
||
|
|
|
||
|
|
// And negative.
|
||
|
|
r = ctr;
|
||
|
|
while(true) {
|
||
|
|
ZZCell prev = firstpara;
|
||
|
|
firstpara = Nile2Iter.findStruct(firstpara, -1, false);
|
||
|
|
if(firstpara == null) break;
|
||
|
|
ld.detect(firstpara);
|
||
|
|
|
||
|
|
ft = paragraph(firstpara, prev, null, null, null);
|
||
|
|
|
||
|
|
beginningSentence[0] = true;
|
||
|
|
r = placeParagraph(into, ft, firstpara, rect,
|
||
|
|
-1, r.y - paraskip, 0);
|
||
|
|
|
||
|
|
if(r.y < 0) break;
|
||
|
|
}
|
||
|
|
// into.dump();
|
||
|
|
Flob cursf = into.findFlob(null, accursed);
|
||
|
|
// p("Cursf: "+cursf);
|
||
|
|
if(cursf != null)
|
||
|
|
((SplitCellFlob1)cursf).addCurs(into, ZZCursorReal.getOffs(view),
|
||
|
|
Color.red);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
// vim: set syntax=java :
|