Ticket #6694: snapbutton.patch

File snapbutton.patch, 11.6 KB (added by akks, 14 years ago)
  • src/org/openstreetmap/josm/actions/mapmode/DrawAction.java

     
    11// License: GPL. See LICENSE file for details.
    22package org.openstreetmap.josm.actions.mapmode;
    33
     4import javax.swing.JCheckBoxMenuItem;
    45import static org.openstreetmap.josm.tools.I18n.tr;
    56import static org.openstreetmap.josm.tools.I18n.trn;
    67import static org.openstreetmap.josm.tools.I18n.marktr;
     8import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
    79
    810import java.awt.AWTEvent;
    911import java.awt.BasicStroke;
     
    3638
    3739import javax.swing.SwingUtilities;
    3840import org.openstreetmap.josm.Main;
     41import org.openstreetmap.josm.actions.JosmAction;
    3942import org.openstreetmap.josm.command.AddCommand;
    4043import org.openstreetmap.josm.command.ChangeCommand;
    4144import org.openstreetmap.josm.command.Command;
     
    5053import org.openstreetmap.josm.data.osm.Way;
    5154import org.openstreetmap.josm.data.osm.WaySegment;
    5255import org.openstreetmap.josm.data.osm.visitor.paint.PaintColors;
     56import org.openstreetmap.josm.gui.MainMenu;
    5357import org.openstreetmap.josm.gui.MapFrame;
    5458import org.openstreetmap.josm.gui.MapView;
    5559import org.openstreetmap.josm.gui.layer.Layer;
     
    8993    private Shortcut extraShortcut;
    9094    private Shortcut backspaceShortcut;
    9195   
    92     boolean snapOn;
     96    private JCheckBoxMenuItem snapCheckboxMenuItem;
     97   
    9398           
    9499    public DrawAction(MapFrame mapFrame) {
    95100        super(tr("Draw"), "node/autonode", tr("Draw nodes"),
     
    99104        // Add extra shortcut N
    100105        extraShortcut = Shortcut.registerShortcut("mapmode:drawfocus", tr("Mode: Draw Focus"), KeyEvent.VK_N, Shortcut.GROUP_EDIT);
    101106        Main.registerActionShortcut(this, extraShortcut);
    102 
     107       
     108        snapCheckboxMenuItem = MainMenu.addWithCheckbox(Main.main.menu.editMenu, new SnapChangeAction(),  MainMenu.WINDOW_MENU_GROUP.VOLATILE);
     109        snapHelper.setMenuCheckBox(snapCheckboxMenuItem);
    103110        cursorJoinNode = ImageProvider.getCursor("crosshair", "joinnode");
    104111        cursorJoinWay = ImageProvider.getCursor("crosshair", "joinway");
    105112    }
     
    134141        drawTargetHighlight = Main.pref.getBoolean("draw.target-highlight", true);
    135142        wayIsFinished = false;
    136143        snapHelper.init();
     144        snapCheckboxMenuItem.getAction().setEnabled(true);
    137145       
    138146        backspaceShortcut = Shortcut.registerShortcut("mapmode:backspace", tr("Backspace in Add mode"), KeyEvent.VK_BACK_SPACE, Shortcut.GROUP_EDIT);
    139147        Main.registerActionShortcut(new BackSpaceAction(), backspaceShortcut);
     
    159167        DataSet.removeSelectionListener(this);
    160168        Main.unregisterActionShortcut(backspaceShortcut);
    161169        snapHelper.unsetFixedMode();
    162 
     170        snapCheckboxMenuItem.getAction().setEnabled(false);
     171       
    163172        removeHighlighting();
    164173        try {
    165174            Toolkit.getDefaultToolkit().removeAWTEventListener(this);
     
    264273        // request focus in order to enable the expected keyboard shortcuts
    265274        //
    266275        Main.map.mapView.requestFocus();
    267 
     276       
    268277        if(e.getClickCount() > 1 && mousePos != null && mousePos.equals(oldMousePos)) {
    269278            // A double click equals "user clicked last node again, finish way"
    270279            // Change draw tool only if mouse position is nearly the same, as
     
    324333                }
    325334            } else { // n==null, no node found in clicked area
    326335                EastNorth mouseEN = Main.map.mapView.getEastNorth(e.getX(), e.getY());
    327                 newEN = snapOn ? snapHelper.getSnapPoint(mouseEN) : mouseEN;
     336                newEN = snapHelper.isSnapOn() ? snapHelper.getSnapPoint(mouseEN) : mouseEN;
    328337                n = new Node(newEN); //create node at clicked point
    329338                newNode = true;
    330339            }
     
    698707            angle += angle < 0 ? 360 : 0;
    699708        }
    700709       
    701         if (snapOn) snapHelper.checkAngleSnapping(currentMouseEastNorth,angle);
     710        snapHelper.checkAngleSnapping(currentMouseEastNorth,angle);
    702711       
    703712        Main.map.statusLine.setAngle(angle);
    704713        Main.map.statusLine.setHeading(hdg);
     
    948957        if (!Main.map.mapView.getBounds().contains(mousePos)) return;
    949958       
    950959        Graphics2D g2 = g;
    951         if (snapOn) snapHelper.draw(g2,mv);
     960        snapHelper.drawIfNeeded(g2,mv);
    952961        if (!drawHelperLine || wayIsFinished || shift) return;
    953962       
    954963        if (!snapHelper.isActive()) { // else use color and stoke from  snapHelper.draw
    955964            g2.setColor(selectedColor);
    956965            g2.setStroke(new BasicStroke(3, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
     966        } else {
     967            if (!snapHelper.drawConstructionGeometry) return;
    957968        }
    958969        GeneralPath b = new GeneralPath();
    959970        Point p1=mv.getPoint(currentBaseNode);
     
    10181029            } else {
    10191030                rv += " " + tr("Continue way from last node.");
    10201031            }
    1021             if (snapOn) {
     1032            if (snapHelper.isSnapOn()) {
    10221033                rv += " "+ tr("Angle snapping ON.");
    10231034            }
    10241035        }
     
    10921103 }
    10931104
    10941105    private class SnapHelper {
     1106        boolean snapOn; // snapping is turned on
     1107       
    10951108        private boolean active; // snapping is activa for current mouse position
    10961109        private boolean fixed; // snap angle is fixed
    10971110        private boolean absoluteFix; // snap angle is absolute
     1111       
     1112        private boolean drawConstructionGeometry;
     1113        private boolean showProjectedPoint;
     1114        private boolean showAngle;
     1115       
    10981116        EastNorth dir2;
    10991117        EastNorth projected;
    11001118        String labelText;
     
    11101128        Color snapHelperColor;
    11111129        private Stroke normalStroke;
    11121130        private Stroke helperStroke;
    1113 
     1131       
     1132        JCheckBoxMenuItem checkBox;
     1133       
    11141134        private  void init() {
    11151135            snapOn=false;
     1136            checkBox.setState(snapOn);
    11161137            fixed=false; absoluteFix=false;
    1117            
     1138                       
    11181139            Collection<String> angles = Main.pref.getCollection("draw.anglesnap.angles",
    11191140                    Arrays.asList("0","30","45","60","90","120","135","150","210","225","240","270","300","315","330"));
    11201141           
     
    11301151                i++;
    11311152            }
    11321153            snapAngleTolerance = Main.pref.getDouble("draw.anglesnap.tolerance", 5.0);
     1154            drawConstructionGeometry = Main.pref.getBoolean("draw.anglesnap.drawConstructionGeometry", true);
     1155            showProjectedPoint = Main.pref.getBoolean("draw.anglesnap.drawProjectedPoint", true);
     1156            showAngle = Main.pref.getBoolean("draw.anglesnap.showAngle", true);
    11331157
    11341158            normalStroke = new BasicStroke(3, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
    11351159            snapHelperColor = Main.pref.getColor(marktr("draw angle snap"), Color.ORANGE);
     
    11461170            labelText=null;
    11471171        }
    11481172
    1149         private void draw(Graphics2D g2, MapView mv) {
     1173        private void drawIfNeeded(Graphics2D g2, MapView mv) {
     1174            if (!snapOn) return;
    11501175            if (!active) return;
    11511176            Point p1=mv.getPoint(currentBaseNode);
    11521177            Point p2=mv.getPoint(dir2);
    11531178            Point p3=mv.getPoint(projected);
    11541179            GeneralPath b;
    1155            
    1156             g2.setColor(snapHelperColor);
    1157             g2.setStroke(helperStroke);
    1158            
    1159             b = new GeneralPath();
    1160             if (absoluteFix) {
    1161                 b.moveTo(p2.x,p2.y);
    1162                 b.lineTo(2*p1.x-p2.x,2*p1.y-p2.y); // bi-directional line
    1163             } else {
    1164                 b.moveTo(p2.x,p2.y);
    1165                 b.lineTo(p3.x,p3.y);
    1166             }
    1167             g2.draw(b);
     1180            if (drawConstructionGeometry) {
     1181                g2.setColor(snapHelperColor);
     1182                g2.setStroke(helperStroke);
    11681183
     1184                b = new GeneralPath();
     1185                if (absoluteFix) {
     1186                    b.moveTo(p2.x,p2.y);
     1187                    b.lineTo(2*p1.x-p2.x,2*p1.y-p2.y); // bi-directional line
     1188                } else {
     1189                    b.moveTo(p2.x,p2.y);
     1190                    b.lineTo(p3.x,p3.y);
     1191                }
     1192                g2.draw(b);
     1193            }
     1194
    11691195            g2.setColor(selectedColor);
    11701196            g2.setStroke(normalStroke);
    11711197            b = new GeneralPath();
     
    11741200            g2.draw(b);
    11751201           
    11761202            g2.drawString(labelText, p3.x-5, p3.y+20);
    1177             g2.setStroke(normalStroke);
    1178             g2.drawOval(p3.x-5, p3.y-5, 10, 10); // projected point
     1203            if (showProjectedPoint) {
     1204                g2.setStroke(normalStroke);
     1205                g2.drawOval(p3.x-5, p3.y-5, 10, 10); // projected point
     1206            }
    11791207           
    11801208            g2.setColor(snapHelperColor);
    11811209            g2.setStroke(helperStroke);
     
    11901218        /* If mouse position is close to line at 15-30-45-... angle, remembers this direction
    11911219         */
    11921220        private void checkAngleSnapping(EastNorth currentEN, double angle) {
     1221            if (!snapOn) return;
    11931222            if (!absoluteFix && previousNode==null) return;
    11941223           
    11951224            double nearestAngle;
     
    12071236
    12081237                EastNorth p0 = currentBaseNode.getEastNorth();
    12091238                e0=p0.east(); n0=p0.north();
    1210 
    1211                 if (fixed) {
    1212                     if (absoluteFix) labelText = "=";
    1213                                 else labelText = String.format(fixFmt, (int) nearestAngle);
    1214                 } else labelText = String.format("%d", (int) nearestAngle);
    12151239               
     1240                if (showAngle)  {
     1241                    if (fixed) {
     1242                        if (absoluteFix) labelText = "=";
     1243                                    else labelText = String.format(fixFmt, (int) nearestAngle);
     1244                    } else labelText = String.format("%d", (int) nearestAngle);
     1245                } else {
     1246                    if (fixed) {
     1247                        if (absoluteFix) labelText = "=";
     1248                        else labelText = String.format(tr("FIX"),0);
     1249                    } else labelText="";
     1250                }
     1251               
    12161252                if (absoluteFix) {
    12171253                    de=0; dn=1;
    12181254                } else {
     
    12601296                snapOn=true;
    12611297                unsetFixedMode();
    12621298            }
     1299            checkBox.setState(snapOn);
    12631300        }
    1264 
     1301       
     1302        private void toggleSnapping() {
     1303            snapOn = !snapOn;
     1304            checkBox.setState(snapOn);
     1305            unsetFixedMode();
     1306        }
     1307               
    12651308        private boolean isActive() {
    12661309            return active;
    12671310        }
     
    12891332            absoluteFix=true;
    12901333            lastAngle=hdg;
    12911334        }
     1335
     1336        private void setMenuCheckBox(JCheckBoxMenuItem checkBox) {
     1337            this.checkBox = checkBox;
     1338        }
     1339
     1340        private boolean isSnapOn() {
     1341            return snapOn;
     1342        }
    12921343    }
     1344   
     1345    private class SnapChangeAction extends JosmAction {
     1346        public SnapChangeAction() {
     1347             super(tr("Angle snapping"), "anglesnap",
     1348                   tr("Switches angle snapping mode while drawing"),
     1349                   Shortcut.registerShortcut("draw:anglesnap", tr("Draw: {0}",tr("Angle snapping")),
     1350                   KeyEvent.VK_H, Shortcut.GROUP_EDIT), false);
     1351             putValue("help", ht("/Action/Draw/AngleSnap"));
     1352        }
     1353        @Override
     1354        public void actionPerformed(ActionEvent e) {
     1355               if (snapHelper!=null) snapHelper.toggleSnapping();
     1356        }
     1357       
     1358    }
    12931359}