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

219 lines
7.7 KiB
Plaintext

/*
CursorView.zob
*
* 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 Antti-Juhani Kaijanaho
*/
package org.gzigzag;
import java.awt.*;
import java.util.*;
class CursorView implements FlobView, ZOb {
public static boolean dbg = false;
static final void p(String s) { if(dbg) ZZLogger.log(s); }
static final void pa(String s) { ZZLogger.log(s); }
STRUCTPARAMS {
float horizonlevel
= (float) 0.5;
float pointerradius
= (float) 0.3;
float sizefactor
= (float) 0.8;
int initdepth
= 2;
int maxdepth
= 8;
Color linecolor
= Color.blue;
double arrowhead_angle
= Math.PI / 6;
int arrowhead_length
= 5;
}
// translation (rotation && scaling) matrices
double a00, a01, a10, a11, b00, b01, b10, b11;
INITIALIZE {
if (!(0 < horizonlevel && horizonlevel < 1)) {
throw new ZZError("horizonlevel parameter outside ]0,1[");
}
if (!(0 < pointerradius && pointerradius < 1)) {
throw new ZZError("pointerradius parameter outside ]0,1[");
}
a00 = arrowhead_length * Math.cos(arrowhead_angle);
a01 = arrowhead_length * Math.sin(arrowhead_angle);
a10 = arrowhead_length * -Math.sin(arrowhead_angle);
a11 = arrowhead_length * Math.cos(arrowhead_angle);
b00 = arrowhead_length * Math.cos(arrowhead_angle);
b01 = arrowhead_length * -Math.sin(arrowhead_angle);
b10 = arrowhead_length * Math.sin(arrowhead_angle);
b11 = arrowhead_length * Math.cos(arrowhead_angle);
}
Hashtable drawn;
private void drawPointerCells(FlobSet into, FlobFactory fact,
ZZCell centercell, Point centerpoint,
int radius, int level, float sfactor) {
if (level > maxdepth) return;
if (drawn.containsKey(centercell)) return;
Vector pointers = new Vector();
{
Dimension s = fact.getSize(null, 1);
int width = (int) (s.width * sfactor);
int height = (int) (s.height * sfactor);
int x = centerpoint.x - width / 2;
int y = centerpoint.y - height / 2;
p("radius = " + radius + ", x = " + x + ", y = "
+ y + ", width = " + width + ", height = "
+ height + ", centercell = " + centercell);
Flob fl = fact.makeFlob(into, centercell, centercell, 1,
x, y, level, width, height);
drawn.put(centercell, centercell);
}
for (Enumeration e = ZZCursorReal.getPointers(centercell);
e.hasMoreElements();) {
ZZCell c = (ZZCell) e.nextElement();
pointers.addElement(c);
p("Found cursor " + c);
}
int n = pointers.size();
p("n = " + n);
if (n == 0) return;
int prad = (int) (pointerradius * radius);
double baseangle = Math.PI / (n + 1);
int newradius;
{
double a = prad - prad * Math.cos(baseangle);
double b = prad * Math.sin(baseangle);
newradius = (int) Math.sqrt(a * a + b * b);
p("a = " + a + ", b = " + b + ", newradius = " + newradius);
}
for (int i = 0; i < n; i++) {
ZZCell c = (ZZCell) pointers.elementAt(i);
if (ZZCursorReal.get(c) != centercell) pa("WRONG CURSOR CELL FOUND!!!");
double angle = (i + 1) * baseangle;
p("angle = " + angle + " rad, " + angle * 180 / Math.PI + " deg");
int x = (int)(centerpoint.x + prad * Math.cos(angle));
int y = (int)(centerpoint.y + prad * Math.sin(angle));
drawPointerCells(into, fact, c, new Point(x, y), newradius,
level + 1, sfactor * sizefactor);
}
}
public void raster(final FlobSet into, FlobFactory fact,
ZZCell view, String[] dims, ZZCell accursed) {
ZZCell c = accursed;
Point pt = new Point(into.getSize().width / 2,
into.getSize().width / 2);
ZZCell ccand = ZZCursorReal.get(c);
if (ccand != null) {
c = ccand;
pt.y /= 2;
}
drawn = new Hashtable();
drawPointerCells(into, fact, c, pt,
into.getSize().width, initdepth, 1);
// Draw the cursor arrows
into.iterDepth(new FlobSet.DepthIter() {
public void act(Flob[] flobs, int start, int n) {
for(int i = start; i < start+n; i++) {
ZZCell pointer = flobs[i].c;
if (pointer == null) continue;
ZZCell pointee = ZZCursorReal.get(pointer);
if (pointee == null) continue;
p("pointer = " + pointer + ", pointee = " + pointee);
Flob from = flobs[i];
Flob[] tos = into.findFlobs(null, pointee);
for (int j = 0; j < tos.length; j++) {
Flob to = (Flob) tos[j];
int[] cs = new int[16];
// we make the arrow body in two parts:
// one from head to arrow point and one
// from arrow point to tail
cs[0] = from.x + from.w / 2;
cs[1] = from.y;
cs[2] = to.x + to.w / 2;
cs[3] = to.y + to.h;
double or1 = (cs[0] + cs[2]) / 2;
double or2 = (cs[1] + cs[3]) / 2;
cs[6] = cs[2];
cs[7] = cs[3];
cs[2] = (int) (or1 + 0.5);
cs[3] = (int) (or2 + 0.5);
cs[4] = cs[2];
cs[5] = cs[3];
double v1 = cs[0] - cs[2];
double v2 = cs[1] - cs[3];
double vlen = Math.sqrt(v1*v1 + v2*v2);
v1 = v1 / vlen;
v2 = v2 / vlen;
cs[8] = (int) (or1 + 0.5);
cs[9] = (int) (or2 + 0.5);
cs[10] = (int) (v1 * a00 + v2 * a01 + or1 + 0.5);
cs[11] = (int) (v1 * a10 + v2 * a11 + or2 + 0.5);
cs[12] = (int) (or1 + 0.5);
cs[13] = (int) (or2 + 0.5);
cs[14] = (int) (v1 * b00 + v2 * b01 + or1 + 0.5);
cs[15] = (int) (v1 * b10 + v2 * b11 + or2 + 0.5);
into.add(new LineDecor(cs, cs.length,
linecolor,
(from.d + to.d) / 2));
}
}
}
}, true);
}
}