Newer
Older
AnchorGarden_M / src / main / java / jaist / css / covis / cls / Variable.java
@Motoki Miura Motoki Miura on 21 Jun 2022 12 KB reset path
package jaist.css.covis.cls;

import jaist.css.covis.CoVisBuffer;
import jaist.css.covis.PPPath;
import jaist.css.covis.Selectable;
import jaist.css.covis.hist.CVHist_Var;

import java.awt.BasicStroke;
import java.awt.Color;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.TreeMap;

import javax.swing.JFrame;
import javax.swing.JOptionPane;

import org.piccolo2d.PNode;
import org.piccolo2d.nodes.PPath;
import org.piccolo2d.nodes.PText;
import org.piccolo2d.util.PDimension;

public class Variable extends PPPath implements Layoutable, Selectable, ToFront, Move {
	public static BasicStroke roundrectStroke = new BasicStroke(6f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND,
			90.0f);

	private static final long serialVersionUID = -2274392520995258292L;

	public Covis_Type cv_class;
	public Class<?> type;
	public Class<?> elementType;
	boolean isArray = false;
	// public Covis_Object cv_class_for_tooptip;
	// public static Variable selected_stamp;
	// public static ArrayList<Variable> stamps;
	// static{
	// stamps = new ArrayList<Variable>();
	// }
	private boolean isSelected;

	public boolean isEnabled = true;
	public Covis_Type object = null;// これがあるとMember

	PPath handle;
	PText caption;

	public Anchor anchor;
	private String varname_base;
	private HashSet<String> varnames;

	public CVHist_Var cvhist;

	long toFront_ts = 0;
	public CoVisBuffer buffer;

	public static float top = 0;

	public void setVarName_Base(String s) {
		varname_base = s;
		// varnames.add(s);
	}

	public boolean isEnabled() {
		return isEnabled;
	}

	public void setEnabled(boolean b) {
		isEnabled = b;
		anchor.setAnchorEnabled(b);
	}

	public Variable(Covis_Type co, JFrame frame, CoVisBuffer buf, boolean isMember) {
		cv_class = co;
		buffer = buf;
		varnames = new HashSet<String>();
		if (cv_class instanceof Covis_Array) {
			// 型(クラス・プリミティブ)選択
			String s;
			if (((Covis_Array) cv_class).elementClassStr == null) {
				s = (String) JOptionPane.showInputDialog(
						frame,
						"Choose Type of the Array",
						"Choose Type",
						JOptionPane.QUESTION_MESSAGE,
						null,
						ClassStamp.possibilities,
						Covis_Array.lastSelectedClass);
				if ((s != null) && (s.length() > 0)) {
					// System.out.println(s+" Selected.");
					Covis_Array.lastSelectedClass = s;
				} else {
					type = null;
				}
			} else {
				s = ((Covis_Array) cv_class).elementClassStr;
			}
			try {
				Class<?> c = Class.forName("jaist.css.covis.cls.Covis_" + s);
				Constructor<?> constructor = c.getConstructor(CoVisBuffer.class, boolean.class);
				cv_class = (Covis_Type) constructor.newInstance(buffer, true);

				type = Array.newInstance(c, 4).getClass();
				elementType = cv_class.getClass();

				System.out.println("array " + type.toString());
				System.out.println("ele " + elementType.toString());
				isArray = true;
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (InstantiationException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			} catch (InvocationTargetException e) {
				e.printStackTrace();
			} catch (SecurityException e) {
				e.printStackTrace();
			} catch (NoSuchMethodException e) {
				e.printStackTrace();
			}
		} else {
			type = cv_class.getClass();
			elementType = type;
		}
		setPaint(cv_class.getClassColor());
		setStrokePaint(Color.gray);
		setStroke(new BasicStroke(1));

		// co.setScale(0.3f);
		// addChild(cv_class);
		// layout(0);

		addAttribute("info", "ClassStamp " + this.toString());
		// addAttribute("selectable", this);
		addAttribute("moveTargetY", this);
		addAttribute("dragLayout", this);

		handle = new PPPath(this.getPathReference());
		handle.addAttribute("moveTargetY", this);
		handle.addAttribute("dragLayout", this);
		handle.setTransparency(0.0f);
		handle.setPaint(Color.pink);
		handle.setStrokePaint(Color.red);
		handle.setStroke(roundrectStroke);
		handle.setPickable(true);
		handle.raiseToTop();
		handle.addAttribute("info", "ClassStamp handle");
		// handle.addAttribute("selectable", this);
		// handle.addAttribute("exclusiveSelectable", stamps);
		addChild(handle);

		if (!isMember) {
			varname_base = cv_class.getNextVarName(isArray);
			caption = new PText(getTypeName() + "  " + varname_base);
			caption.scale(2.2f);
			caption.setOffset(10, 3);
			caption.addAttribute("moveTargetY", this);
			caption.addAttribute("dragLayout", this);
			addChild(caption);
			caption.addAttribute("popupMenu", new VariableMenu(this));
		}

		if (cv_class instanceof Covis_Object || isArray) {
			anchor = new Anchor(type, this);
			anchor.setVarName(varname_base);
			addChild(anchor);
			anchor.setOffset(245, 30);
			if (!isMember) {
				anchor.setAnchorEnabled(true);
			}
		} else {
			// プリミティブなので,1つだけ追加
			Covis_primitive prim = (Covis_primitive) cv_class;
			addChild(prim);
			prim.setPathToRectangle(0, 0, 30, (float) getHeight());
			prim.setStroke(new BasicStroke(2));
			prim.justify();
			prim.setOffset(getWidth() - prim.getWidth(), (getHeight() - prim.getHeight()) / 2);
			prim.addAttribute("moveTargetY", this);
			prim.addAttribute("dragLayout", this);
			prim.valueText.addAttribute("moveTargetY", this);
			prim.valueText.addAttribute("dragLayout", this);
			prim.valueText.addAttribute("popupMenu", new VariableMenu(this));
		}

		addAttribute("popupMenu", new VariableMenu(this));
		handle.addAttribute("popupMenu", new VariableMenu(this));
		// stamps.add(this);
	}

	public String getTypeName() {
		if (!isArray) {
			// if (type.isAssignableFrom(Covis_Object.class)){
			return cv_class.getClsName();
		} else {
			return cv_class.getClsName() + "[]";
		}
	}

	public void layout(int dur) {
		layoutExceptOne(null, dur);
	}

	public void layoutExceptOne(PNode operationNode, int dur) {
		var col = getChildrenReference();
		TreeMap<Integer, PNode> map = new TreeMap<Integer, PNode>();
		for (var o : col) {
			PNode p = (PNode) o;
			map.put((int) p.getYOffset(), p);
		}

		double offsetx = 10;
		double endx = 10;
		double offsety = 10;
		double endy = 10;
		double maxx = 0, maxy = 0;
		for (PNode p : map.values()) {
			// p.setOffset(offsetx, offsety);
			double px = p.getFullBounds().width;
			double py = p.getFullBounds().height;
			if (maxx < offsetx + endx + px)
				maxx = offsetx + endx + px;
			if (maxy < offsety + endy + py)
				maxy = offsety + endy + py;
			if (operationNode != p)
				p.animateToPositionScaleRotation(offsetx, offsety + top, 1, 0, dur);
			offsety += py;
			offsety += 10;
		}
		animateToBounds(0, top, maxx, maxy, dur);
	}

	public ArrayList<Selectable> getAllChildren() {
		return null;
	}

	public boolean isSelected() {
		return isSelected;
	}

	public void setSelected(boolean f, ArrayList<Selectable> list) {
		isSelected = f;
		if (f)
			handle.setTransparency(0.8f);
		else
			handle.setTransparency(0.0f);
		if (f && list != null && !list.contains(this))
			list.add(this);
		if (!f && list != null && list.contains(this))
			list.remove(this);
	}

	public PNode theNode() {
		return this;
	}

	public void toggleSelected(ArrayList<Selectable> list) {
		setSelected(!isSelected, list);
	}

	public void removeLabel(Hashtable<PNode, PNode> trash) {
		if (trash != null)
			trash.put(this, getParent());
		removeFromParent();
	}
	// public PNode getToolTipNode(){
	// if (cv_class_for_tooptip == null) {
	// cv_class_for_tooptip = cv_class.Covis_clone();
	// cv_class_for_tooptip.setScale(0.5f);
	// }
	// return cv_class_for_tooptip;
	// }

	public String getBaseVarName() {
		return varname_base;
	}

	public void addVarNames(String prefix) {
		// System.out.println("Variable.addVarNames"+prefix);
		varnames.add(prefix);
	}

	public String getVarName() {
		StringBuffer sb = new StringBuffer();
		for (String s : getVarNamesAry()) {
			sb.append(s + "\n");
		}
		if (sb.length() == 0)
			return sb.toString();
		return sb.toString().substring(0, sb.toString().length() - 1);
	}

	public ArrayList<String> getVarNamesAry() {
		ArrayList<String> news = new ArrayList<String>();
		if (this instanceof VariableM) {
			String sepdot = ".";
			if (object instanceof Covis_Array)
				sepdot = "";

			for (String s : varnames) {
				news.add(s + sepdot + varname_base);
			}
		} else {
			news.add(varname_base);
		}
		return news;
	}

	public void clearVarNamesAry() {
		varnames.clear();
	}

	// この変数を削除する
	public void dispose() {
		if (anchor != null && anchor.destObject != null) {
			anchor.destObject.detach(anchor);
		}
		Layoutable layout = (Layoutable) getParent();
		removeFromParent();
		layout.layout(200);
	}

	// 変数名変更
	public String rename(JFrame f) {
		String input;
		while (true) {
			if (isArray) {
				input = JOptionPane.showInputDialog(f, "Input new name for " + cv_class.getClsName() + "[] variable.",
						varname_base);
			} else {
				input = JOptionPane.showInputDialog(f, "Input new name for " + cv_class.getClsName() + " variable.",
						varname_base);
			}
			if (input == null)
				return null;
			if (input.equals(""))
				return null;
			// 変数名重複チェック
			// 親に聞くのが一番
			VarField parent = (VarField) getParent();

			if (parent.checkExistName(input, this)) {
				JOptionPane.showMessageDialog(null, "Same name is already used.\n\nPlease input other name.",
						"Rename Error", JOptionPane.WARNING_MESSAGE);
				continue;
			}
			if (!input.matches("^[a-zA-Z_][a-zA-Z0-9]*")) {
				JOptionPane.showMessageDialog(null, "Name should start with alphabet or _.\n\nPlease input other name.",
						"Rename Error", JOptionPane.WARNING_MESSAGE);
				continue;
			}
			break;
		}

		varname_base = input;
		if (anchor != null) {
			anchor.setVarName(varname_base);
		}
		caption.setText(getTypeName() + "  " + varname_base);
		if (anchor != null && anchor.destObject != null) {
			anchor.destObject.tooltip = null; // 変数名ツールチップを再構築
		}
		return varname_base;
	}

	public void toFront() {
		toFront(System.currentTimeMillis());
	}

	public void toFront(long ts) {
		if (toFront_ts == ts)
			return;
		toFront_ts = ts;
		PNode parent = getParent();
		if (parent != null) {
			// removeFromParent();
			parent.addChild(this);
			if (parent instanceof ToFront)
				((ToFront) parent).toFront(ts);
		}
	}

	public void move(PDimension d) {
		translate(d.getWidth(), d.getHeight()); // 履歴に関係ない動作
		if (anchor != null)
			anchor.start_RewindThread();
	}

	public String getConstructorInfo() {
		if (cv_class instanceof Covis_Object || isArray)
			return getTypeName() + " " + varname_base + ";";
		else
			return getTypeName() + " " + varname_base + " = " + ((Covis_primitive) cv_class).value + ";"; // getValue()にすると,''がとれてしまうので
	}

	public void setCVHist(CVHist_Var _cvhist) {
		cvhist = _cvhist;
	}

	public String getEditValueInfo() {
		if (cv_class instanceof Covis_Object || isArray)
			return getTypeName() + " " + varname_base + ";";
		else
			return varname_base + " = " + ((Covis_primitive) cv_class).value + ";"; // getValue()にすると,''がとれてしまうので
	}

	public void appendVarNameRecursive(Hashtable<Integer, Object> checked) {
		// System.out.println(varname_base);
		if (anchor == null)
			return;
		if (anchor.destObject != null) {
			// if (checked.containsKey(this.hashCode())) return;
			// checked.put(this.hashCode(), this);
			// System.out.println("V append "+getVarName());
			anchor.destObject.appendVarNameRecursive(this, checked);
		}
	}

	public static String getShortestName(ArrayList<String> src) {
		if (src.size() == 0)
			return null;
		if (src.size() == 1)
			return src.get(0);
		String temp = src.get(0);
		for (String s : src) {
			if (s.length() < temp.length())
				temp = s;
		}
		return temp;
	}
}