/* CreateTrackCommand.java - * * (C) 2005 fnh */ package jfig.demo; // import java.awt.*; import java.awt.Container; import java.awt.GridLayout; import java.awt.event.*; import javax.swing.*; import java.util.Enumeration; import java.util.Vector; import jfig.gui.JModularEditor; import jfig.canvas.*; import jfig.commands.*; import jfig.objects.*; import jfig.utils.MouseMapper; /** * add the selected track to the current drawing. * Provides 'smart place' option. */ public class CreateTrackCommand extends Command { FigObject target = null; Point pos = null; static FigObject globalLastUsedTrack = null; public CreateTrackCommand( FigBasicEditor editor, FigCanvas objectCanvas ) { super( editor, objectCanvas ); statusMessage( "L: smart place object M: place object R: cancel" ); editor.hideAllObjectCorners(); objectCanvas.changeRubberbandMode( FigCanvasRubberband.pointRubber ); ready = false; if (target == null) { if (globalLastUsedTrack == null) return; target = globalLastUsedTrack.copy(); // move new copy back to origin for correct rubberbanding Point p = target.getPosition(); target.move( -p.getX(), -p.getY() ); objectCanvas.setRubberbandBasePoint( objectCanvas.getTrafo().getScreenCoords( new Point(0,0) )); objectCanvas.changeRubberbandMode( FigCanvasRubberband.objectRubber, objectCanvas.getTrafo(), target ); //objectCanvas.changeRubberbandMode( FigCanvasRubberband.bboxRubber, // objectCanvas.getTrafo(), // target.getBbox() ); } } public void setTrack( FigObject o ) { target = o; globalLastUsedTrack = target; // editor.addTmpObject( target ); objectCanvas.setRubberbandBasePoint( objectCanvas.getTrafo().getScreenCoords( new Point(0,0) )); objectCanvas.changeRubberbandMode( FigCanvasRubberband.objectRubber, objectCanvas.getTrafo(), target ); } public void execute() { if (target != null) { editor.insertIntoObjectList( target ); editor.getUndoStack().push( this ); objectCanvas.doFullRedraw(); } } public void undo() { if (target != null) { editor.deleteFromObjectList( target ); objectCanvas.doFullRedraw(); } } private void rotateTarget( double degrees ) { try { Point sp = objectCanvas.getRawMousePositionOrNull(); Point wp = objectCanvas.getTrafo().getWorldCoordsSnapped( sp ); // System.out.println( "XXX rotateTarget: " + sp + " " + wp ); if (target != null) { target.rotate( wp, degrees*Math.PI*2.0/360.0 ); } } catch( Exception e ) { e.printStackTrace(); } } public void mousePressed( MouseEvent evt ) { Point WP = getWorldCoords( evt ); Point SP = getScreenCoords( evt ); // safety check if (target == null) { throw new RuntimeException( "Internal error: target object is null!" ); } if (MouseMapper.isRightClick(evt)) { // cancel if (target != null) editor.deleteTmpObject( target ); target = null; objectCanvas.changeRubberbandMode( FigCanvasRubberband.pointRubber ); objectCanvas.doFullRedraw(); ready = true; } else if (MouseMapper.isMiddleClick(evt)) { // smart place pos = WP; boolean nearEnough = smartPlaceToNearestMarker( WP ); if (nearEnough) { execute(); ready = true; notifyEditor(); } } else { // left click, raw place pos = WP; // System.out.println( "-#- WP= " + WP ); // System.out.println( "-#- pos= " + target.getPosition() ); // target.move( WP.getX(), WP.getY() ); execute(); ready = true; notifyEditor(); } } // mousePressed public void keyPressed( KeyEvent evt ) { char key = evt.getKeyChar(); int code = evt.getKeyCode(); Point p = null; JModularEditor ed = (JModularEditor) editor; if (evt.isActionKey()) { // some keys for panning etc. switch (code) { case KeyEvent.VK_DOWN : ed.doPanDown( evt ); break; case KeyEvent.VK_UP : ed.doPanUp( evt ); break; case KeyEvent.VK_LEFT : ed.doPanLeft( evt ); break; case KeyEvent.VK_RIGHT: ed.doPanRight(evt ); break; case KeyEvent.VK_HOME : ed.doPanHome( evt ); break; } } else { switch( key ) { case 'f' : ed.doZoomFit( null ); break; case 's' : rotateTarget( -18.0 ); target.rebuild(); break; case 'S' : rotateTarget( -36.0 ); target.rebuild(); break; case 'r' : rotateTarget( 18.0 ); target.rebuild(); break; case 'R' : rotateTarget( 36.0 ); target.rebuild(); break; case 'x' : case 'X' : p = target.getPosition(); target.mirrorX( p.getX(), p.getY() ); target.rebuild(); break; case 'y' : case 'Y' : p = target.getPosition(); target.mirrorY( p.getX(), p.getY() ); target.rebuild(); break; case 'z' : objectCanvas.doZoomOut(); break; case 'Z' : objectCanvas.doZoomIn(); break; default : System.out.println( "-W- CTC.keyPressed: ignored " + key ); } // switch } // else action key objectCanvas.doFullRedraw(); } public Vector findObjectMarkersViaComments( FigCompound c, Vector v ) { // msg( "-#- CTC.findObjectMarkers..." ); if (v == null) v = new Vector(); for( Enumeration e = c.getMembers().elements(); e.hasMoreElements(); ) { FigObject tmp = (FigObject) e.nextElement(); String comment = tmp.getComment(); if (comment == null) continue; if ("start".equals( comment ) || "end".equals( comment )) { // msg( "-#- found marker: " + comment + " " + tmp ); v.addElement( tmp ); } } // msg( " total: " + v.size() + " markers." ); return v; } public Vector findObjectMarkersViaLayers( FigCompound c, Vector v ) { // msg( "-#- CTC.findObjectMarkers..." ); if (v == null) v = new Vector(); for( Enumeration e = c.getMembers().elements(); e.hasMoreElements(); ) { FigObject tmp = (FigObject) e.nextElement(); if (tmp instanceof FigCompound) { // recurse findObjectMarkersViaLayers( (FigCompound) tmp, v ); } else { // check non-compound objects for matching layer int layer = tmp.getLayer(); if ( (layer == ProfiGleisFactory.START_MARKER_LAYER) || (layer == ProfiGleisFactory.END_MARKER_LAYER)) { // msg( "-#- found marker at " + tmp.getPosition() ); v.addElement( tmp ); } } } // msg( " total: " + v.size() + " markers." ); return v; } private Point[] getMarkerPositions( Vector v ) { Point[] pp = new Point[ v.size() ]; for( int i=0; i < v.size(); i++ ) { pp [i] = ((FigObject) v.elementAt(i)).getPosition(); } return pp; } public boolean smartPlaceToNearestMarker( Point wp ) { // msg( "-#- CTC.findObjectMarkers: " + wp ); FigCompound nearestMatch = null; FigObject nearestMarker1 = null; // on target object FigObject nearestMarker2 = null; // on existing object double nearestDistance = Double.MAX_VALUE; // msg( "-1- target: " ); Vector v1 = findObjectMarkersViaLayers( (FigCompound)target, null ); Point[] pp1 = getMarkerPositions( v1 ); // Point targetCenter = targetBbox.getCenterPoint(); // msg( "-2- others: " ); FigBbox targetBbox = target.getBbox(); for( Enumeration e = editor.getObjects(); e.hasMoreElements(); ) { Object tmp = e.nextElement(); if (tmp instanceof FigCompound) { FigCompound comp = (FigCompound) tmp; FigBbox compBbox = comp.getBbox(); // Point compCenter = compBbox.getCenterPoint(); // near enough for detailed checking ? double NEAR_ENOUGH = 10000; // double distance = targetCenter.distance( compCenter ); double distance = targetBbox.minManhattanDistance( compBbox ); // msg( "... ... " + distance ); if (distance < NEAR_ENOUGH) { Vector v2 = findObjectMarkersViaLayers( comp, null ); Point[] pp2 = getMarkerPositions( v2 ); for( int i=0; i < pp1.length; i++ ) { for( int j=0; j < pp2.length; j++ ) { double d = pp1[i].distance( pp2[j] ); // msg( "... ... ... " + i + " " + j + " " + d ); if (d < nearestDistance) { nearestMatch = comp; nearestMarker1 = (FigObject) v1.elementAt(i); nearestMarker2 = (FigObject) v2.elementAt(j); nearestDistance = d; } } } } // near_enough } } // for all objects // msg( "*** nearestMatch: " + nearestMatch ); // msg( "*** nearestMarker1: " + nearestMarker1 ); // msg( "*** nearestMarker2: " + nearestMarker2 ); // msg( "*** distance : " + nearestDistance ); if (nearestDistance < 4800) { Point t = target.getPosition(); // current position of target obj Point x = nearestMarker1.getPosition(); // current pos of marker on target Point z = nearestMarker2.getPosition(); // nearest external marker pos target.move( z.getX() - t.getX() + (t.getX() - x.getX()), z.getY() - t.getY() + (t.getY() - x.getY()) ); return true; } return false; } public void msg( String s ) { System.out.println( s ); } public String getDescription() { return "create track"; } public String toString() { return "CreateTrackCommand"; } } // class CreateTrackCommand