Newer
Older
AnchorGarden_M / src / main / java / jaist / css / covis / cls / Variable.java
@motoki miura motoki miura on 9 May 2022 11 KB first commit
package jaist.css.covis.cls;

import jaist.css.covis.CoVisBuffer;
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.List;
import java.util.TreeMap;

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

import edu.umd.cs.piccolo.PNode;
import edu.umd.cs.piccolo.nodes.PPath;
import edu.umd.cs.piccolo.nodes.PText;
import edu.umd.cs.piccolo.util.PDimension;

public class Variable extends PPath 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;
		}
		setPathToRectangle(0,0,250,40);
		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 PPath(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.moveToFront();
		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) {
		List<PNode> col = getChildrenReference();
		TreeMap<Double,PNode> map = new TreeMap<Double, PNode>();
		for(PNode p: col) map.put(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;
	}
}