Warning: session_start(): open(/var/lib/php/sessions/sess_6fsv1fmpo8ht0hn2aound84gfc, O_RDWR) failed: No space left on device (28) in /var/www/tb-usercake/models/config.php on line 51
Warning: session_start(): Failed to read session data: files (path: /var/lib/php/sessions) in /var/www/tb-usercake/models/config.php on line 51
sclass BaseBase {
S text;
S textForRender() { ret text; }
}
sclass Base extends BaseBase {
}
sclass CirclesAndLines {
new L circles;
new L lines;
Class extends Arrow> arrowClass = Arrow;
Class extends Circle> circleClass = Circle;
transient Lock lock = fairLock();
transient S defaultImageID = #1007372;
double imgZoom = 1;
Pt translate;
Circle hoverCircle; // which one we are hovering over
O onUserMadeArrow, onUserMadeCircle, onLayoutChange;
O onFullLayoutChange, onDeleteCircle, onDeleteLine;
transient BufferedImage imageForUserMadeNodes;
static int maxDistanceToLine = 20; // for clicking
transient S backgroundImageID = defaultBackgroundImageID;
static S defaultBackgroundImageID = #1007195;
static Color defaultLineColor = Color.white;
// auto-visualize
Circle circle_autoVis(S text, S visualizationText, double x, double y) {
ret addAndReturn(circles,
nu(circleClass, +x, +y, +text,
quickvis := visualizationText,
img := processImage(quickVisualizeOr(visualizationText, defaultImageID))));
}
S makeVisualizationText(S text) {
ret possibleGlobalID(text) ? "" : text;
}
Circle circle_autoVis(S text, double x, double y) {
ret circle_autoVis(text, makeVisualizationText(text), x, y);
}
Circle circle(BufferedImage img, double x, double y, S text) {
ret addAndReturn(circles, nu(circleClass, +x, +y, +text, img := processImage(img));
}
Circle circle(S text, BufferedImage img, double x, double y) {
ret circle(img, x, y, text);
}
Circle circle(S text, double x, double y) {
ret addAndReturn(circles, nu(circleClass, +x, +y, +text, img := processImage(imageForUserMadeNodes());
}
Circle addCircle(S imageID, double x, double y) {
ret addCircle(imageID, x, y, "");
}
Circle addCircle(S imageID, double x, double y, S text) {
ret addAndReturn(circles, nu(circleClass, +x, +y, +text, img := processImage(loadImage2(imageID))));
}
Arrow findArrow(Circle a, Circle b) {
for (Line l : getWhere(lines, +a, +b))
if (l instanceof Arrow)
ret (Arrow) l;
null;
}
Line addLine(Circle a, Circle b) {
Line line = findWhere(lines, +a, +b);
if (line == null)
lines.add(line = nu(Line, +a, +b));
ret line;
}
Arrow arrow(Circle a, S text, Circle b) {
ret addArrow(a, b, text);
}
Arrow addArrow(Circle a, Circle b) {
ret addArrow(a, b, "");
}
Arrow addArrow(Circle a, Circle b, S text) {
ret addAndReturn(lines, nu(arrowClass, +a, +b, +text));
}
BufferedImage makeImage(int w, int h) {
BufferedImage bg = renderTiledBackground(backgroundImageID, w, h, ptX(translate), ptY(translate));
if (!lock.tryLock()) null;
try {
// Lines
for (Line l : lines) {
Pt a = translatePt(translate, l.a.pt(w, h));
Pt b = translatePt(translate, l.b.pt(w, h));
if (l << Arrow)
drawThoughtArrow(bg, l.a.img(this), a.x, a.y, l.b.img(this), b.x, b.y, l.color);
else
drawThoughtLine(bg, l.a.img(this), a.x, a.y, l.b.img(this), b.x, b.y, l.color);
S text = l.textForRender();
if (nempty(text))
drawThoughtLineText(bg, l.a.img(this), a.x, a.y, l.b.img(this), b.x, b.y, text, l.color);
}
// Circles
for (Circle c : circles) {
Pt p = translatePt(translate, c.pt(w, h));
drawThoughtCircle(bg, c.img(this), p.x, p.y);
S text = c.textForRender();
if (nempty(text))
drawThoughtCircleText(bg, c.img(this), p, text);
if (c == hoverCircle)
drawThoughtCirclePlus(bg, c.img(this), p.x, p.y);
}
} finally {
lock.unlock();
}
ret bg;
}
Canvas showAsFrame(int w, int h) {
Canvas canvas = showAsFrame();
frameInnerSize(canvas, w, h);
centerFrame(getFrame(canvas));
ret canvas;
}
Canvas showAsFrame() {
ret (Canvas) swing(func {
Canvas canvas = makeCanvas();
showCenterFrame(canvas);
ret canvas;
});
}
Canvas makeCanvas() {
fO makeImg = func(int w, int h) { makeImage(w, h) };
final Canvas canvas = jcanvas(makeImg);
disableImageSurfaceSelector(canvas);
new CircleDragger(this, canvas, r { updateCanvas(canvas, makeImg) });
componentPopupMenu(canvas, voidfunc(JPopupMenu menu) {
Pt p = canvas.pointFromEvent(componentPopupMenu_mouseEvent.get());
final Line l = findLine(canvas, p);
if (l != null)
addMenuItem(menu, "Delete Relation", r {
deleteLine(l);
canvas.update();
});
final Circle c = findCircle(canvas, p);
if (c != null) {
addMenuItem(menu, "Rename...", r { renameCircle(canvas, c) });
addMenuItem(menu, "Delete Circle", r {
deleteCircle(c);
canvas.update();
});
if (c.img != null || c.quickvis != null)
addMenuItem(menu, "Delete Image", r {
c.img = null;
c.quickvis = null;
canvas.update();
});
if (neqic(c.text, c.quickvis))
addMenuItem(menu, "Visualize", r {
thread "Visualizing" {
quickVisualize(c.quickvis);
print("Quickvis done");
swing {
c.img = null;
c.quickvis = c.text;
canvas.update();
}
}
});
}
});
ret canvas;
}
Canvas show() { ret showAsFrame(); }
Canvas show(int w, int h) { ret showAsFrame(w, h); }
Circle findCircle(S text) {
for (Circle c : circles) if (eq(c.text, text)) ret c;
for (Circle c : circles) if (eqic(c.text, text)) ret c;
null;
}
void renameCircle(final Canvas canvas, final Circle c) {
final JTextField tf = jtextfield(c.text);
showFormTitled("Rename circle",
"Old name", jlabel(c.text),
"New name", tf,
r {
c.text = getTextTrim(tf);
canvas.update();
});
}
void clear {
clearAll(circles, lines);
}
// only finds actually containing circles
Circle findCircle(ImageSurface canvas, Pt p) {
p = untranslatePt(translate, p);
new Lowest best;
for (Circle c : circles)
if (c.contains(this, canvas, p))
best.put(c, pointDistance(p, c.pt(canvas)));
ret best!;
}
Circle findNearestCircle(ImageSurface canvas, Pt p) {
new Lowest best;
for (Circle c : circles)
if (c.contains(this, canvas, p))
best.put(c, pointDistance(p, c.pt(canvas)));
ret best.get();
}
BufferedImage processImage(BufferedImage img) {
ret scaleImage(img, imgZoom);
}
void deleteCircle(Circle c) {
for (Line l : cloneList(lines))
if (l.a == c || l.b == c) deleteLine(l);
circles.remove(c);
pcallF(onDeleteCircle, c);
}
void deleteLine(Line l) {
lines.remove(l);
pcallF(onDeleteLine, l);
}
void openPlusDialog(final Circle c, final ImageSurface canvas) {
if (c == null) ret;
final JTextField tfFrom = jtextfield(c.text);
final JTextField tfRel = jtextfield(web_defaultRelationName());
final JTextField tfTo = jtextfield();
showFormTitled("Add connection",
"From node", tfFrom,
"Connection name", tfRel,
"To node", tfTo,
func {
S sA = getTextTrim(tfFrom);
Circle a = eq(sA, c.text) ? c : findOrMakeCircle(sA);
if (a == null) { messageBox("Not found: " + getTextTrim(tfFrom)); false; }
Circle b = findOrMakeCircle(getTextTrim(tfTo));
if (b == null) { messageBox("Not found: " + getTextTrim(tfTo)); false; }
if (a == b) { infoBox("Can't connect circle to itself for now"); false; }
Arrow arrow = arrow(a, getTextTrim(tfRel), b);
((Canvas) canvas).update();
pcallF(onUserMadeArrow, arrow);
null;
});
awtLater(tfRel, 100, r { requestFocus(tfRel) });
}
Circle findOrMakeCircle(S text) {
Circle c = findCircle(text);
if (c == null) {
c = circle(imageForUserMadeNodes(), random(), random(), text);
pcallF(onUserMadeCircle, c);
}
ret c;
}
BufferedImage imageForUserMadeNodes() {
if (imageForUserMadeNodes == null)
imageForUserMadeNodes = whiteImage(20, 20);
ret imageForUserMadeNodes;
}
Line findLine(Canvas is, Pt p) {
p = untranslatePt(translate, p);
new Lowest best;
for (Line line : lines) {
double d = distancePointToLineSegment(line.a.pt(is), line.b.pt(is), p);
if (d <= maxDistanceToLine)
best.put(line, d);
}
ret best!;
}
} // end of class CirclesAndLines
sclass Circle extends Base {
transient BufferedImage img;
double x, y;
//static BufferedImage defaultImage;
S quickvis;
BufferedImage img(CirclesAndLines cal) {
if (img != null) ret img;
if (nempty(quickvis)) img = quickVisualize(quickvis);
//if (defaultImage == null) defaultImage = loadImage2(#1007372);
ret cal.imageForUserMadeNodes();
}
Pt pt(ImageSurface is) {
ret pt(is.getWidth(), is.getHeight());
}
Pt pt(int w, int h) {
ret new Pt(iround(x*w), iround(y*h));
}
bool contains(CirclesAndLines cal, ImageSurface is, Pt p) {
ret pointDistance(p, pt(is)) <= thoughtCircleSize(img(cal))/2+1;
}
}
sclass Line extends Base {
Circle a, b;
transient Color color = CirclesAndLines.defaultLineColor;
Line setColor(Color color) {
this.color = color;
this;
}
}
Line > Arrow {}
sclass CircleDragger extends MouseAdapter {
CirclesAndLines cal;
ImageSurface is;
O update;
int dx, dy;
Circle circle;
Pt startPoint;
*(CirclesAndLines *cal, ImageSurface *is, O *update) {
if (containsInstance(is.tools, CircleDragger)) ret;
is.tools.add(this);
is.addMouseListener(this);
is.addMouseMotionListener(this);
}
public void mouseMoved(MouseEvent e) {
Pt p = is.pointFromEvent(e);
Circle c = cal.findCircle(is, p);
if (c != cal.hoverCircle) {
cal.hoverCircle = c;
callF(update);
}
}
public void mousePressed(MouseEvent e) {
if (e.getButton() == MouseEvent.BUTTON1) {
Pt p = is.pointFromEvent(e);
startPoint = p;
circle = cal.findCircle(is, p);
if (circle != null) {
dx = p.x-iround(circle.x*is.getWidth());
dy = p.y-iround(circle.y*is.getHeight());
} else {
Pt t = unnull(cal.translate);
dx = p.x-t.x;
dy = p.y-t.y;
}
}
}
public void mouseDragged(MouseEvent e) {
if (startPoint == null) ret;
Pt p = is.pointFromEvent(e);
if (circle != null) {
circle.x = (p.x-dx)/(double) is.getWidth();
circle.y = (p.y-dy)/(double) is.getHeight();
pcallF(cal.onLayoutChange, circle);
callF(update);
} else {
cal.translate = new Pt(p.x-dx, p.y-dy);
callF(update);
}
}
public void mouseReleased(MouseEvent e) {
mouseDragged(e);
if (eq(is.pointFromEvent(e), startPoint))
cal.openPlusDialog(circle, is);
circle = null;
startPoint = null;
}
}