Newer
Older
AnchorGarden_M / src / main / java / jaist / css / covis / CoVisWindow_SelectionRegionHandler.java
@motoki miura motoki miura on 21 Jun 2022 9 KB ppath error
package jaist.css.covis;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Stroke;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Hashtable;

import org.piccolo2d.PNode;
import org.piccolo2d.event.PDragSequenceEventHandler;
import org.piccolo2d.event.PInputEvent;
import org.piccolo2d.nodes.PPath;
import org.piccolo2d.util.PBounds;

/**
 * Selectableを範囲選択
 * @author miuramo
 *
 */
public class CoVisWindow_SelectionRegionHandler extends PDragSequenceEventHandler {
	AnchorGarden viewer;

	PPPath selection;

	private Stroke[] strokes = null;

	private float strokeNum = 0;

	final static int NUM_STROKES = 10;

	final static int DASH_WIDTH = 15;

	Point2D cmp; // ドラッグ開始座標

	Point2D cp; //ドラッグ中の座標

	public ArrayList<Selectable> tempSelect;

//	double dist_max_ext_cp; //そのときの距離
	PBounds initialBounds; //ドラッグ開始時の視野

	PNode targetPN;
	Point2D targetPNorigin;
	Point2D targetPNtopleft;
	
	PNode selectTarget;
	int dragCount = 0;
	
	public Hashtable<PNode,PNode> trash; // DELキーで選択削除したものを,一旦蓄えておく.次に削除するまで,一段のみアンドゥ可能
	public boolean undoExecuted = false;

	public CoVisWindow_SelectionRegionHandler(AnchorGarden _viewer) {
		this.viewer = _viewer;

		float[] dash = { DASH_WIDTH, DASH_WIDTH };
		strokes = new Stroke[NUM_STROKES];
		for (int i = 0; i < NUM_STROKES; i++) {
			strokes[i] = new BasicStroke(2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 1, dash, i);
		}
		tempSelect = new ArrayList<Selectable>();
		
		trash = new Hashtable<PNode,PNode>();
	}

	public void startDrag(PInputEvent e) {
		super.startDrag(e);

		//クリック選択トグル用
		if (e.getPickedNode().getAttribute("selectable")!=null){
			selectTarget = (PNode) e.getPickedNode().getAttribute("selectable");
		}
		dragCount = 0;

		// 範囲選択用 ターゲットベース (not カメラビューベース)
		if (e.getPickedNode() instanceof PNode && (e.getPickedNode().getAttribute("drawTarget")!=null)){
			targetPN = (PNode) e.getPickedNode().getAttribute("drawTarget");
			System.out.println(targetPN.getClass().getName());
			targetPNorigin = (Point2D) e.getPickedNode().getAttribute("drawOffset");
			if (targetPNorigin == null) targetPNorigin = new Point2D.Double();

			if (targetPN != null) {
				Point2D p = e.getPositionRelativeTo(e.getPickedNode());
				if (targetPNorigin != null) p.setLocation(p.getX()+targetPNorigin.getX(),p.getY()+targetPNorigin.getY());
				targetPNtopleft = p;

				//しかし,選択範囲の赤枠はカメラにつける
				cmp = e.getPositionRelativeTo(viewer.getCanvas().getCamera());
				selection = new PPPath();
				selection.setPathToRectangle((float) cmp.getX(), (float) cmp.getY(), 0, 0);
				selection.setStrokePaint(Color.red);//赤
				selection.setPaint(null);
				selection.setStroke(strokes[0]);
				viewer.getCanvas().getCamera().addChild(selection);
			}
		} else {
			targetPN = null;
		}
//		tempSelect.clear();
		viewer.setShowToolTip(false);

	}

	public void drag(PInputEvent e) {
		super.drag(e);

		if (targetPN != null){
			// 選択範囲の更新
			cp = e.getPositionRelativeTo(viewer.getCanvas().getCamera());
			Rectangle2D selectionViewRect = new Rectangle2D.Double(cmp.getX(),cmp.getY(),0,0);
			selectionViewRect.add(cp);
			selectionViewRect.add(cmp);
//			float cp_cmp_x = (float)(cp.getX() - cmp.getX());
//			float cp_cmp_y = (float)(cp.getY() - cmp.getY());
//			selection.setPathToRectangle((float) cmp.getX(), (float) cmp.getY(), cp_cmp_x, cp_cmp_y);
			selection.setPathTo(selectionViewRect);

			// 選択対象物(Selectable)を検索
			Point2D p = e.getPositionRelativeTo(e.getPickedNode());
			if (targetPNorigin != null) p.setLocation(p.getX()+targetPNorigin.getX(),p.getY()+targetPNorigin.getY());
			Rectangle2D layerb = new PBounds();
			layerb.add(targetPNtopleft);
			layerb.add(p);

//			ノート上のShortStroke ノートに絞って探索
//			if (e.getPickedNode().getAttribute("info") != null){
//			String attr = (String)e.getPickedNode().getAttribute("info");
//			if (attr.startsWith("noteCams")){
//			PNode d = (PNode) e.getPickedNode().getAttribute("drawTarget");
			Collection<PNode> col = targetPN.getAllNodes();
			for(Object o:col){
				PNode pn = (PNode)o;
				if (pn instanceof Selectable){
//					if (layerb.contains(pn.getGlobalBounds())){ //完全に含まれるとき選択
					Rectangle2D pngb = pn.getBounds(); // Label はoffsetで動いているので,Boundsでは比較できない
//					System.out.println("original BB" + pngb.toString());
//					System.out.println("original AT" + pn.getTransform().toString());
					pn.getTransform().transform(pngb, pngb);
//					System.out.println("modified BB" + pngb.toString());
					if (layerb.intersects(pngb)){ //少しでも重なれば選択
						((Selectable)pn).setSelected(true, tempSelect);
//						if (!tempSelect.contains((Selectable)pn)) tempSelect.add((Selectable)pn);
						pn.repaint();
					}
				}
			}
//			}
//			}
//			}

////			ドラッグ開始した,Daishi上のLabelのみに絞って探索
//			if (e.getPickedNode().getAttribute("info") != null){
//			String attr = (String)e.getPickedNode().getAttribute("info");
//			if (attr.startsWith("Daishi")){
//			Daishi d = (Daishi) e.getPickedNode();
//			for(PPath cd: d.childDaishies){
//			Collection col = cd.getAllNodes();
//			for(Object o:col){
//			PNode pn = (PNode)o;
////			if (layerb.contains(pn.getGlobalBounds())){ //完全に含まれるとき選択
//			if (layerb.intersects(pn.getBounds())){ //少しでも重なれば選択
//			if (pn instanceof Selectable){
//			((Selectable)pn).setSelected(true, tempSelect);
////			if (!tempSelect.contains((Selectable)pn)) tempSelect.add((Selectable)pn);
//			pn.repaint();
//			}
//			}
//			}
//			}
//			}
//			}
			ArrayList<Selectable> tempSelect4Check = new ArrayList<Selectable>(tempSelect);
			for(Selectable sl : tempSelect4Check){
				PNode pn = (PNode) sl;
				Rectangle2D pngb = pn.getBounds();
				pn.getTransform().transform(pngb, pngb);
//				if (!layerb.contains(((PNode)sl).getGlobalBounds())){ //完全に含まれるとき選択
				if (!layerb.intersects(pngb)){ //少しでも重なれば選択
					sl.setSelected(false,tempSelect);
				}
			}

			// 右下にドラッグしているときの,青い点線矩形の点線パターンを変化させる
			float origStrokeNum = strokeNum;
			strokeNum = (strokeNum + 0.3f) % NUM_STROKES; 
			if ((int) strokeNum != (int) origStrokeNum) {
				selection.setStroke(strokes[(int) strokeNum]);
			}
		}
		dragCount++;

//		// 選択範囲に完全に含まれるSelectableがあれば選択する//カメラビュー中心主義
//		PAffineTransform at = viewer.getCanvas().getCamera().getViewTransform();
//		Rectangle2D globalb = selection.getGlobalBounds();
//		Rectangle2D layerb = new Rectangle2D.Double();
//		at.inverseTransform(globalb, layerb); //グローバルからカメラへ

		// 以前は全部探索 しかし,効率がわるい
//		for(Student stu: viewer.buffer.id2stuHash.values()){
//		for(PPath d: stu.daishi.childDaishies){
//		Collection col = d.getAllNodes();
//		for(Object o:col){
//		PNode pn = (PNode)o;
////		if (layerb.contains(pn.getGlobalBounds())){ //完全に含まれるとき選択
//		if (layerb.intersects(pn.getGlobalBounds())){ //少しでも重なれば選択
//		if (pn instanceof Selectable){
//		((Selectable)pn).setSelected(true);
//		if (!tempSelect.contains((Selectable)pn)) tempSelect.add((Selectable)pn);
//		pn.repaint();
//		}
//		}
//		}
//		}
//		}
	}

	public void endDrag(PInputEvent e) {
		super.endDrag(e);
		cp = e.getPositionRelativeTo(viewer.getCanvas().getCamera());
		if (selection != null) selection.removeFromParent();
		selection = null;
		
		if (selectTarget != null && dragCount < 3){
			if (selectTarget.getBounds().contains(e.getPositionRelativeTo(selectTarget))){//離したときもラベルの上なら
				((Selectable)selectTarget).toggleSelected(tempSelect); //選択をトグルする
//				System.out.println("Toggle");
			}
			selectTarget = null;
		}

//		tempSelect.clear();
		viewer.setShowToolTip(true);

//		if (cmp.getX() < cp.getX() && cmp.getY() < cp.getY()) {
//		// カメラ座標から,グローバル(パネル)座標への変換
//		PAffineTransform at = viewer.getCanvas().getCamera().getViewTransform();
//		Rectangle2D globalb = selection.getGlobalBounds();
//		Rectangle2D layerb = new Rectangle2D.Double();
//		at.inverseTransform(globalb, layerb);
//		viewer.getCanvas().getCamera().animateViewToCenterBounds(layerb, true, 1000);
//		}
	}

	public void removeSelected() {
		trash.clear();
		for(Selectable sel: tempSelect){
			if (sel.isSelected()) sel.removeLabel(trash);
		}
		tempSelect.clear();
		undoExecuted = false;
		viewer.canvas.cam.repaint();
	}
//	public void undoRemoveSelected(){
//		if (trash.size() == 0){
//			System.out.println("No Undoable Items.");
//			return;
//		}
//		if (!undoExecuted){
//			for(PNode pn: trash.keySet()){
//				PNode parent = trash.get(pn);
//				((Historical)pn).addWithHist(parent);
//				tempSelect.add((Selectable)pn);
//			}
//			undoExecuted = true;
//		} else {
//			for(PNode pn: trash.keySet()){
//				((Historical)pn).removeWithHist();
//			}
//			undoExecuted = false;
//			tempSelect.clear();
//		}
//		viewer.canvas.cam.repaint();
//	}

	public void toFrontSelected() {
		for(Selectable sel : tempSelect){
			PNode pn = (PNode) sel;
			PNode parentnode = pn.getParent();
			parentnode.addChild(pn);
		}
	}

	//選択解除
	public void DeSelect() {
		for(Selectable sel : tempSelect){
			sel.setSelected(false, null);
		}
		tempSelect.clear();
	}
}