001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.plugins.streetside.mode; 003 004import static org.openstreetmap.josm.tools.I18n.tr; 005 006import java.awt.Graphics2D; 007import java.awt.Point; 008import java.awt.event.InputEvent; 009import java.awt.event.MouseEvent; 010import java.util.Objects; 011import java.util.concurrent.ConcurrentSkipListSet; 012 013import javax.swing.SwingUtilities; 014 015import org.openstreetmap.josm.data.Bounds; 016import org.openstreetmap.josm.data.coor.LatLon; 017import org.openstreetmap.josm.data.osm.OsmPrimitive; 018import org.openstreetmap.josm.gui.MainApplication; 019import org.openstreetmap.josm.gui.MapView; 020import org.openstreetmap.josm.gui.layer.OsmDataLayer; 021import org.openstreetmap.josm.plugins.streetside.StreetsideAbstractImage; 022import org.openstreetmap.josm.plugins.streetside.StreetsideData; 023import org.openstreetmap.josm.plugins.streetside.StreetsideImage; 024import org.openstreetmap.josm.plugins.streetside.StreetsideLayer; 025import org.openstreetmap.josm.plugins.streetside.gui.StreetsideMainDialog; 026import org.openstreetmap.josm.plugins.streetside.history.StreetsideRecord; 027import org.openstreetmap.josm.plugins.streetside.history.commands.CommandMove; 028import org.openstreetmap.josm.plugins.streetside.history.commands.CommandTurn; 029import org.openstreetmap.josm.plugins.streetside.utils.StreetsideProperties; 030 031/** 032 * Handles the input event related with the layer. Mainly clicks. 033 * 034 * @author nokutu 035 */ 036public class SelectMode extends AbstractMode { 037 private StreetsideAbstractImage closest; 038 private StreetsideAbstractImage lastClicked; 039 private final StreetsideRecord record; 040 private boolean nothingHighlighted; 041 private boolean imageHighlighted; 042 043 /** 044 * Main constructor. 045 */ 046 public SelectMode() { 047 record = StreetsideRecord.getInstance(); 048 } 049 050 @Override 051 public void mousePressed(MouseEvent e) { 052 if (e.getButton() != MouseEvent.BUTTON1) { 053 return; 054 } 055 StreetsideAbstractImage closest = getClosest(e.getPoint()); 056 if (!(MainApplication.getLayerManager().getActiveLayer() instanceof StreetsideLayer) 057 && closest != null && MainApplication.getMap().mapMode == MainApplication.getMap().mapModeSelect) { 058 lastClicked = this.closest; 059 StreetsideLayer.getInstance().getData().setSelectedImage(closest); 060 return; 061 } else if (MainApplication.getLayerManager().getActiveLayer() != StreetsideLayer.getInstance()) { 062 return; 063 } 064 // Double click 065 if (e.getClickCount() == 2 && StreetsideLayer.getInstance().getData().getSelectedImage() != null && closest != null) { 066 closest.getSequence().getImages().forEach(StreetsideLayer.getInstance().getData()::addMultiSelectedImage); 067 } 068 lastClicked = this.closest; 069 this.closest = closest; 070 if (closest != null && StreetsideLayer.getInstance().getData().getMultiSelectedImages().contains(closest)) { 071 return; 072 } 073 // ctrl+click 074 if (e.getModifiers() == (InputEvent.BUTTON1_MASK | InputEvent.CTRL_MASK) && closest != null) { 075 StreetsideLayer.getInstance().getData().addMultiSelectedImage(closest); 076 // shift + click 077 } else if ( 078 e.getModifiers() == (InputEvent.BUTTON1_MASK | InputEvent.SHIFT_MASK) 079 && lastClicked instanceof StreetsideImage 080 ) { 081 if (this.closest != null 082 && this.closest.getSequence() == (lastClicked).getSequence()) { 083 int i = this.closest.getSequence().getImages().indexOf(this.closest); 084 int j = lastClicked.getSequence().getImages().indexOf(lastClicked); 085 StreetsideLayer.getInstance().getData().addMultiSelectedImage( 086 i < j 087 ? new ConcurrentSkipListSet<>(this.closest.getSequence().getImages().subList(i, j + 1)) 088 : new ConcurrentSkipListSet<>(this.closest.getSequence().getImages().subList(j, i + 1)) 089 ); 090 } 091 // click 092 } else { 093 StreetsideLayer.getInstance().getData().setSelectedImage(closest); 094 } 095 } 096 097 @Override 098 public void mouseDragged(MouseEvent e) { 099 StreetsideAbstractImage highlightImg = StreetsideLayer.getInstance().getData().getHighlightedImage(); 100 if ( 101 MainApplication.getLayerManager().getActiveLayer() == StreetsideLayer.getInstance() 102 && SwingUtilities.isLeftMouseButton(e) 103 && highlightImg != null && highlightImg.getLatLon() != null 104 ) { 105 Point highlightImgPoint = MainApplication.getMap().mapView.getPoint(highlightImg.getTempLatLon()); 106 if (e.isShiftDown()) { // turn 107 StreetsideLayer.getInstance().getData().getMultiSelectedImages().parallelStream().filter(img -> !(img instanceof StreetsideImage) || StreetsideProperties.DEVELOPER.get()) 108 .forEach(img -> img.turn(Math.toDegrees(Math.atan2(e.getX() - highlightImgPoint.getX(), -e.getY() + highlightImgPoint.getY())) - highlightImg.getTempHe())); 109 } else { // move 110 LatLon eventLatLon = MainApplication.getMap().mapView.getLatLon(e.getX(), e.getY()); 111 LatLon imgLatLon = MainApplication.getMap().mapView.getLatLon(highlightImgPoint.getX(), highlightImgPoint.getY()); 112 StreetsideLayer.getInstance().getData().getMultiSelectedImages().parallelStream().filter(img -> !(img instanceof StreetsideImage) || StreetsideProperties.DEVELOPER.get()) 113 .forEach(img -> img.move(eventLatLon.getX() - imgLatLon.getX(), eventLatLon.getY() - imgLatLon.getY())); 114 } 115 StreetsideLayer.invalidateInstance(); 116 } 117 } 118 119 @Override 120 public void mouseReleased(MouseEvent e) { 121 final StreetsideData data = StreetsideLayer.getInstance().getData(); 122 if (data.getSelectedImage() == null) { 123 return; 124 } 125 if (!Objects.equals(data.getSelectedImage().getTempHe(), data.getSelectedImage().getMovingHe())) { 126 double from = data.getSelectedImage().getTempHe(); 127 double to = data.getSelectedImage().getMovingHe(); 128 record.addCommand(new CommandTurn(data.getMultiSelectedImages(), to - from)); 129 } else if (!Objects.equals(data.getSelectedImage().getTempLatLon(), data.getSelectedImage().getMovingLatLon())) { 130 LatLon from = data.getSelectedImage().getTempLatLon(); 131 LatLon to = data.getSelectedImage().getMovingLatLon(); 132 record.addCommand(new CommandMove(data.getMultiSelectedImages(), to.getX() - from.getX(), to.getY() - from.getY())); 133 } 134 data.getMultiSelectedImages().parallelStream().filter(Objects::nonNull).forEach(StreetsideAbstractImage::stopMoving); 135 StreetsideLayer.invalidateInstance(); 136 } 137 138 /** 139 * Checks if the mouse is over pictures. 140 */ 141 @Override 142 public void mouseMoved(MouseEvent e) { 143 if (MainApplication.getLayerManager().getActiveLayer() instanceof OsmDataLayer 144 && MainApplication.getMap().mapMode != MainApplication.getMap().mapModeSelect) { 145 return; 146 } 147 if (!StreetsideProperties.HOVER_ENABLED.get()) { 148 return; 149 } 150 151 StreetsideAbstractImage closestTemp = getClosest(e.getPoint()); 152 153 final OsmDataLayer editLayer = MainApplication.getLayerManager().getEditLayer(); 154 if (editLayer != null) { 155 if (closestTemp != null && !imageHighlighted) { 156 if (MainApplication.getMap().mapMode != null) { 157 MainApplication.getMap().mapMode.putValue("active", Boolean.FALSE); 158 } 159 imageHighlighted = true; 160 } else if (closestTemp == null && imageHighlighted && nothingHighlighted) { 161 if (MainApplication.getMap().mapMode != null) { 162 MainApplication.getMap().mapMode.putValue("active", Boolean.TRUE); 163 } 164 nothingHighlighted = false; 165 } else if (imageHighlighted && !nothingHighlighted && editLayer.data != null) { 166 for (OsmPrimitive primivitive : MainApplication.getLayerManager().getEditLayer().data.allPrimitives()) { 167 primivitive.setHighlighted(false); 168 } 169 imageHighlighted = false; 170 nothingHighlighted = true; 171 } 172 } 173 174 if (StreetsideLayer.getInstance().getData().getHighlightedImage() != closestTemp && closestTemp != null) { 175 StreetsideLayer.getInstance().getData().setHighlightedImage(closestTemp); 176 StreetsideMainDialog.getInstance().setImage(closestTemp); 177 StreetsideMainDialog.getInstance().updateImage(false); 178 179 } else if (StreetsideLayer.getInstance().getData().getHighlightedImage() != closestTemp && closestTemp == null) { 180 StreetsideLayer.getInstance().getData().setHighlightedImage(null); 181 StreetsideMainDialog.getInstance().setImage(StreetsideLayer.getInstance().getData().getSelectedImage()); 182 StreetsideMainDialog.getInstance().updateImage(); 183 } 184 185 StreetsideLayer.invalidateInstance(); 186 } 187 188 @Override 189 public void paint(Graphics2D g, MapView mv, Bounds box) { 190 } 191 192 @Override 193 public String toString() { 194 return tr("Select mode"); 195 } 196}