Changeset 29371 in osm for applications


Ignore:
Timestamp:
2013-03-18T21:58:17+01:00 (11 years ago)
Author:
zverik
Message:

some updates to iodb plugin

Location:
applications/editors/josm/plugins/imagery_offset_db/src/iodb
Files:
10 edited
2 copied

Legend:

Unmodified
Added
Removed
  • applications/editors/josm/plugins/imagery_offset_db/src/iodb/CalibrationObject.java

    r28008 r29371  
    1818
    1919    public CalibrationObject(OsmPrimitive object) {
    20         this(object, getLastUserId(object));
     20        this(object, 0);
    2121    }
    2222
     
    2929    }
    3030   
    31     private static long getLastUserId( OsmPrimitive object ) {
    32         return object.getUser() == null ? -1 : object.getUser().getId(); // todo?
    33     }
    34 
    3531    @Override
    3632    public void putServerParams( Map<String, String> map ) {
     
    3834        map.put("object", object instanceof Node ? "node" : "way");
    3935        map.put("id", String.valueOf(object.getId()));
    40         map.put("lastuser", String.valueOf(lastUserId));
    4136    }
    42    
     37
     38    @Override
     39    public String toString() {
     40        return "CalibrationObject{" + "object=" + object + ", lastUserId=" + lastUserId + "position=" + position + ", date=" + date + ", author=" + author + ", description=" + description + ", abandonDate=" + abandonDate + '}';
     41    }
    4342}
  • applications/editors/josm/plugins/imagery_offset_db/src/iodb/DeprecateOffsetAction.java

    r29361 r29371  
    22
    33import java.awt.event.ActionEvent;
    4 import java.awt.event.KeyEvent;
    5 import java.io.IOException;
    6 import java.io.InputStream;
    74import java.io.UnsupportedEncodingException;
    85import java.net.*;
    9 import java.util.ArrayList;
    10 import java.util.Collections;
    11 import java.util.HashMap;
    12 import java.util.List;
    13 import java.util.concurrent.Future;
    14 import java.util.logging.Level;
    15 import java.util.logging.Logger;
    16 import org.openstreetmap.gui.jmapviewer.tilesources.AbstractTMSTileSource;
     6import javax.swing.AbstractAction;
     7import javax.swing.JOptionPane;
    178import org.openstreetmap.josm.Main;
    18 import org.openstreetmap.josm.actions.JosmAction;
    19 import org.openstreetmap.josm.data.coor.LatLon;
    20 import org.openstreetmap.josm.data.projection.Projection;
    21 import org.openstreetmap.josm.gui.MapView;
    22 import org.openstreetmap.josm.gui.PleaseWaitRunnable;
    23 import org.openstreetmap.josm.gui.layer.ImageryLayer;
    24 import org.openstreetmap.josm.gui.progress.ProgressMonitor;
    25 import org.openstreetmap.josm.io.OsmTransferException;
     9import org.openstreetmap.josm.gui.JosmUserIdentityManager;
    2610import static org.openstreetmap.josm.tools.I18n.tr;
    27 import org.openstreetmap.josm.tools.Shortcut;
    28 import org.xml.sax.SAXException;
     11import org.openstreetmap.josm.tools.ImageProvider;
    2912
    3013/**
     
    3316 * @author zverik
    3417 */
    35 public class GetImageryOffsetAction extends JosmAction {
     18public class DeprecateOffsetAction extends AbstractAction {
     19    private ImageryOffsetBase offset;
    3620   
    37     private List<ImageryOffsetBase> offsets;
    38    
    39     public GetImageryOffsetAction() {
    40         super(tr("Get Imagery Offset..."), "getoffset", tr("Download offsets for current imagery from a server"),
    41                 Shortcut.registerShortcut("imageryoffset:get", tr("Imagery: {0}", tr("Get Imagery Offset...")), KeyEvent.VK_I, Shortcut.ALT+Shortcut.CTRL), true);
    42         offsets = Collections.emptyList();
     21    public DeprecateOffsetAction( ImageryOffsetBase offset ) {
     22        super(tr("Deprecate Offset"));
     23        putValue(SMALL_ICON, ImageProvider.get("dialogs", "delete"));
     24        this.offset = offset;
     25        setEnabled(offset != null && !offset.isDeprecated());
    4326    }
    4427
    4528    public void actionPerformed(ActionEvent e) {
    46         Projection proj = Main.map.mapView.getProjection();
    47         LatLon center = proj.eastNorth2latlon(Main.map.mapView.getCenter());
    48         ImageryLayer layer = ImageryOffsetTools.getTopImageryLayer();
    49         String imagery = ImageryOffsetTools.getImageryID(layer);
    50         if( imagery == null )
     29        if( Main.map == null || Main.map.mapView == null || !Main.map.isVisible() )
    5130            return;
    5231       
    53         List<ImageryOffsetBase> offsets = download(center, imagery); // todo: async
    54         /*DownloadOffsets download = new DownloadOffsets();
    55         Future<?> future = Main.worker.submit(download);
    56         try {
    57             future.get();
    58         } catch( Exception ex ) {
    59             ex.printStackTrace();
     32        if( JOptionPane.showConfirmDialog(Main.parent,
     33                tr("Warning: deprecation is irreversible"), // todo: expand
     34                ImageryOffsetTools.DIALOG_TITLE, JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE) != JOptionPane.YES_OPTION ) {
    6035            return;
    61         }*/
    62        
    63         // todo: show a dialog for selecting one of the offsets (without "update" flag)
    64         ImageryOffsetBase offset = new OffsetDialog(offsets).showDialog();
    65         if( offset != null ) {
    66             // todo: use the chosen offset
    67             if( offset instanceof ImageryOffset ) {
    68                 ImageryOffsetTools.applyLayerOffset(layer, (ImageryOffset)offset);
    69             } else if( offset instanceof CalibrationObject ) {
    70                 // todo: select object
     36        }
     37        deprecateOffset(offset);
     38    }
     39
     40    public static void deprecateOffset( ImageryOffsetBase offset ) {
     41        String userName = JosmUserIdentityManager.getInstance().getUserName();
     42        if( userName == null ) {
     43            JOptionPane.showMessageDialog(Main.parent, tr("To store imagery offsets you must be a registered OSM user."), ImageryOffsetTools.DIALOG_TITLE, JOptionPane.ERROR_MESSAGE);
     44            return;
     45        }
     46
     47        String message = "Please enter the reason why you mark this "
     48                + (offset instanceof ImageryOffset ? "imagery offset" : "calibraion object") + " as deprecated:";
     49        String reason = null;
     50        boolean iterated = false;
     51        while( reason == null ) {
     52            reason = JOptionPane.showInputDialog(Main.parent, message, ImageryOffsetTools.DIALOG_TITLE, JOptionPane.PLAIN_MESSAGE);
     53            if( reason == null || reason.length() == 0 ) {
     54                return;
     55            }
     56            if( reason.length() < 3 || reason.length() > 200 ) {
     57                reason = null;
     58                if( !iterated ) {
     59                    message = message + "\n" + tr("Reason text should be 3 to 200 letters long.");
     60                    iterated = true;
     61                }
    7162            }
    7263        }
    73     }
    74    
    75     private List<ImageryOffsetBase> download( LatLon center, String imagery ) {
    76         String base = Main.pref.get("iodb.server.url", "http://offsets.textual.ru/");
    77         String query = "get?lat=" + center.getX() + "&lon=" + center.getY();
    78         List<ImageryOffsetBase> result = null;
     64       
    7965        try {
    80             query = query + "&imagery=" + URLEncoder.encode(imagery, "utf-8");
    81             URL url = new URL(base + query);
    82             System.out.println("url=" + url);
    83             HttpURLConnection connection = (HttpURLConnection)url.openConnection();
    84             connection.connect();
    85             int retCode = connection.getResponseCode();
    86             InputStream inp = connection.getInputStream();
    87             if( inp != null ) {
    88                 result = new IODBReader(inp).parse();
    89                 System.out.println("result.size() = " + result.size());
    90             }
    91             connection.disconnect();
    92         } catch( MalformedURLException ex ) {
    93             // ?
    94         } catch( UnsupportedEncodingException e ) {
    95             // do nothing. WTF is that?
    96         } catch( IOException e ) {
    97             e.printStackTrace();
    98             // ?
    99         } catch( SAXException e ) {
    100             e.printStackTrace();
    101             // ?
    102         }
    103         if( result == null )
    104             result = new ArrayList<ImageryOffsetBase>();
    105         return result;
    106     }
    107    
    108     class DownloadOffsets extends PleaseWaitRunnable {
    109        
    110         private boolean cancelled;
    111 
    112         public DownloadOffsets() {
    113             super(tr("Downloading calibration data"));
    114             cancelled = false;
    115         }
    116 
    117         @Override
    118         protected void realRun() throws SAXException, IOException, OsmTransferException {
    119             // todo: open httpconnection to server and read xml
    120             if( cancelled )
    121                 return;
    122            
    123         }
    124 
    125         @Override
    126         protected void finish() {
    127             if( cancelled )
    128                 return;
    129             // todo: parse xml and return an array of ImageryOffsetBase
    130         }
    131        
    132         @Override
    133         protected void cancel() {
    134             cancelled = true;
     66            String query = "deprecate?id=" + offset.getId()
     67                + "&author=" + URLEncoder.encode(userName, "UTF8")
     68                + "&reason=" + URLEncoder.encode(reason, "UTF8");
     69            SimpleOffsetQueryTask depTask = new SimpleOffsetQueryTask(query, tr("Notifying the server of the deprecation..."));
     70            Main.worker.submit(depTask);
     71        } catch( UnsupportedEncodingException ex ) {
     72            // WTF
    13573        }
    13674    }
  • applications/editors/josm/plugins/imagery_offset_db/src/iodb/GetImageryOffsetAction.java

    r28008 r29371  
    33import java.awt.event.ActionEvent;
    44import java.awt.event.KeyEvent;
    5 import java.io.IOException;
    65import java.io.InputStream;
    76import java.io.UnsupportedEncodingException;
    87import java.net.*;
    9 import java.util.ArrayList;
    10 import java.util.Collections;
    11 import java.util.HashMap;
    12 import java.util.List;
    13 import java.util.concurrent.Future;
    14 import java.util.logging.Level;
    15 import java.util.logging.Logger;
    16 import org.openstreetmap.gui.jmapviewer.tilesources.AbstractTMSTileSource;
     8import java.util.*;
     9import javax.swing.JOptionPane;
    1710import org.openstreetmap.josm.Main;
     11import org.openstreetmap.josm.actions.AutoScaleAction;
     12import org.openstreetmap.josm.actions.DownloadPrimitiveAction;
    1813import org.openstreetmap.josm.actions.JosmAction;
    1914import org.openstreetmap.josm.data.coor.LatLon;
     15import org.openstreetmap.josm.data.osm.*;
    2016import org.openstreetmap.josm.data.projection.Projection;
    21 import org.openstreetmap.josm.gui.MapView;
    22 import org.openstreetmap.josm.gui.PleaseWaitRunnable;
    2317import org.openstreetmap.josm.gui.layer.ImageryLayer;
    24 import org.openstreetmap.josm.gui.progress.ProgressMonitor;
    25 import org.openstreetmap.josm.io.OsmTransferException;
    2618import static org.openstreetmap.josm.tools.I18n.tr;
    2719import org.openstreetmap.josm.tools.Shortcut;
    28 import org.xml.sax.SAXException;
    2920
    3021/**
     
    3526public class GetImageryOffsetAction extends JosmAction {
    3627   
    37     private List<ImageryOffsetBase> offsets;
    38    
    3928    public GetImageryOffsetAction() {
    4029        super(tr("Get Imagery Offset..."), "getoffset", tr("Download offsets for current imagery from a server"),
    41                 Shortcut.registerShortcut("imageryoffset:get", tr("Imagery: {0}", tr("Get Imagery Offset...")), KeyEvent.VK_I, Shortcut.ALT+Shortcut.CTRL), true);
    42         offsets = Collections.emptyList();
     30                Shortcut.registerShortcut("imageryoffset:get", tr("Imagery: {0}", tr("Get Imagery Offset...")),
     31                KeyEvent.VK_I, Shortcut.ALT_CTRL), true);
    4332    }
    4433
    4534    public void actionPerformed(ActionEvent e) {
     35        if( Main.map == null || Main.map.mapView == null || !Main.map.isVisible() )
     36            return;
    4637        Projection proj = Main.map.mapView.getProjection();
    4738        LatLon center = proj.eastNorth2latlon(Main.map.mapView.getCenter());
     
    5142            return;
    5243       
    53         List<ImageryOffsetBase> offsets = download(center, imagery); // todo: async
    54         /*DownloadOffsets download = new DownloadOffsets();
    55         Future<?> future = Main.worker.submit(download);
    56         try {
    57             future.get();
    58         } catch( Exception ex ) {
    59             ex.printStackTrace();
     44        DownloadOffsetsTask download = new DownloadOffsetsTask(center, layer, imagery);
     45        Main.worker.submit(download);
     46    }
     47
     48    @Override
     49    protected void updateEnabledState() {
     50        boolean state = true;
     51        if( Main.map == null || Main.map.mapView == null || !Main.map.isVisible() )
     52            state = false;
     53        ImageryLayer layer = ImageryOffsetTools.getTopImageryLayer();
     54        if( ImageryOffsetTools.getImageryID(layer) == null )
     55            state = false;
     56        setEnabled(state);
     57    }
     58   
     59    private void showOffsetDialog( List<ImageryOffsetBase> offsets, ImageryLayer layer ) {
     60        if( offsets.isEmpty() ) {
     61            JOptionPane.showMessageDialog(Main.parent,
     62                    tr("No data for this region. Please adjust imagery layer and upload an offset."),
     63                    ImageryOffsetTools.DIALOG_TITLE, JOptionPane.INFORMATION_MESSAGE);
    6064            return;
    61         }*/
    62        
    63         // todo: show a dialog for selecting one of the offsets (without "update" flag)
    64         ImageryOffsetBase offset = new OffsetDialog(offsets).showDialog();
     65        }
     66        final ImageryOffsetBase offset = new OffsetDialog(offsets).showDialog();
    6567        if( offset != null ) {
    66             // todo: use the chosen offset
    6768            if( offset instanceof ImageryOffset ) {
    6869                ImageryOffsetTools.applyLayerOffset(layer, (ImageryOffset)offset);
     70                Main.map.repaint();
    6971            } else if( offset instanceof CalibrationObject ) {
    70                 // todo: select object
     72                OsmPrimitive obj = ((CalibrationObject)offset).getObject();
     73                final List<PrimitiveId> ids = new ArrayList<PrimitiveId>(1);
     74                ids.add(obj);
     75                DownloadPrimitiveAction.processItems(false, ids, false, true);
     76                Main.worker.submit(new AfterCalibrationDownloadTask((CalibrationObject)offset));
     77            }
     78        }
     79    }
     80
     81    class AfterCalibrationDownloadTask implements Runnable {
     82        private CalibrationObject offset;
     83
     84        public AfterCalibrationDownloadTask( CalibrationObject offset ) {
     85            this.offset = offset;
     86        }
     87
     88        @Override
     89        public void run() {
     90            OsmPrimitive p = getCurrentDataSet().getPrimitiveById(offset.getObject());
     91            if( p == null ) {
     92                return;
     93            }
     94            // check for last user
     95            if( offset.getLastUserId() > 0 ) {
     96                long uid = p.getUser().getId();
     97                Date ts = p.getTimestamp();
     98                if( p instanceof Way ) {
     99                    for( Node n : ((Way)p).getNodes() ) {
     100                        if( n.getTimestamp().after(ts) ) {
     101                            ts = n.getTimestamp();
     102                            uid = n.getUser().getId();
     103                        }
     104                    }
     105                }
     106                if( uid != offset.getLastUserId() ) {
     107                    int result = JOptionPane.showConfirmDialog(Main.parent,
     108                            tr("The calibration object has been changed in unknown way.\n"
     109                             + "It may be moved or extended, thus ceasing to be a reliable mark\n"
     110                             + "for imagery calibration. Do you want to notify the server of this?"),
     111                            ImageryOffsetTools.DIALOG_TITLE, JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
     112                    if( result == JOptionPane.YES_OPTION ) {
     113                        DeprecateOffsetAction.deprecateOffset(offset);
     114                        return;
     115                    }
     116                }
     117            }
     118            Main.main.getCurrentDataSet().setSelected(p);
     119            AutoScaleAction.zoomTo(Collections.singleton(p));
     120            if( !Main.pref.getBoolean("iodb.calibration.message", false) ) {
     121                JOptionPane.showMessageDialog(Main.parent,
     122                        tr("An object has been selected on the map. Find the corresponding feature\n"
     123                         + "on the imagery layer and move that layer accordingly.\n"
     124                         + "DO NOT touch the selected object, so it can be used by others later."),
     125                        ImageryOffsetTools.DIALOG_TITLE, JOptionPane.INFORMATION_MESSAGE);
     126                Main.pref.put("iodb.calibration.message", true);
    71127            }
    72128        }
    73129    }
    74130   
    75     private List<ImageryOffsetBase> download( LatLon center, String imagery ) {
    76         String base = Main.pref.get("iodb.server.url", "http://offsets.textual.ru/");
    77         String query = "get?lat=" + center.getX() + "&lon=" + center.getY();
    78         List<ImageryOffsetBase> result = null;
    79         try {
    80             query = query + "&imagery=" + URLEncoder.encode(imagery, "utf-8");
    81             URL url = new URL(base + query);
    82             System.out.println("url=" + url);
    83             HttpURLConnection connection = (HttpURLConnection)url.openConnection();
    84             connection.connect();
    85             int retCode = connection.getResponseCode();
    86             InputStream inp = connection.getInputStream();
    87             if( inp != null ) {
    88                 result = new IODBReader(inp).parse();
    89                 System.out.println("result.size() = " + result.size());
     131    class DownloadOffsetsTask extends SimpleOffsetQueryTask {
     132        private ImageryLayer layer;
     133        private List<ImageryOffsetBase> offsets;
     134
     135        public DownloadOffsetsTask( LatLon center, ImageryLayer layer, String imagery ) {
     136            super(null, tr("Loading imagery offsets..."));
     137            try {
     138                String query = "get?lat=" + center.lat() + "&lon=" + center.lon()
     139                        + "&imagery=" + URLEncoder.encode(imagery, "UTF8");
     140                setQuery(query);
     141            } catch( UnsupportedEncodingException e ) {
     142                throw new IllegalArgumentException(e);
    90143            }
    91             connection.disconnect();
    92         } catch( MalformedURLException ex ) {
    93             // ?
    94         } catch( UnsupportedEncodingException e ) {
    95             // do nothing. WTF is that?
    96         } catch( IOException e ) {
    97             e.printStackTrace();
    98             // ?
    99         } catch( SAXException e ) {
    100             e.printStackTrace();
    101             // ?
    102         }
    103         if( result == null )
    104             result = new ArrayList<ImageryOffsetBase>();
    105         return result;
    106     }
    107    
    108     class DownloadOffsets extends PleaseWaitRunnable {
    109        
    110         private boolean cancelled;
    111 
    112         public DownloadOffsets() {
    113             super(tr("Downloading calibration data"));
    114             cancelled = false;
     144            this.layer = layer;
    115145        }
    116146
    117147        @Override
    118         protected void realRun() throws SAXException, IOException, OsmTransferException {
    119             // todo: open httpconnection to server and read xml
    120             if( cancelled )
    121                 return;
    122            
    123         }
    124 
    125         @Override
    126         protected void finish() {
    127             if( cancelled )
    128                 return;
    129             // todo: parse xml and return an array of ImageryOffsetBase
     148        protected void afterFinish() {
     149            if( !cancelled && offsets != null )
     150                showOffsetDialog(offsets, layer);
    130151        }
    131152       
    132153        @Override
    133         protected void cancel() {
    134             cancelled = true;
     154        protected void processResponse( InputStream inp ) throws UploadException {
     155            offsets = null;
     156            try {
     157                offsets = new IODBReader(inp).parse();
     158            } catch( Exception e ) {
     159                throw new UploadException("Error processing XML response: " + e.getMessage());
     160            }
    135161        }
    136162    }
  • applications/editors/josm/plugins/imagery_offset_db/src/iodb/IODBReader.java

    r27986 r29371  
    5959                if( qName.equals("object") ) {
    6060                    fields.isNode = attributes.getValue("type").equals("node");
     61                } else if( qName.equals("last-user") ) {
     62                    fields.lastUserId = Integer.parseInt(attributes.getValue("id"));
    6163                } else if( qName.equals("imagery-position") ) {
    6264                    fields.imageryPos = parseLatLon(attributes);
     
    102104                } else if( qName.equals("object") ) {
    103105                    fields.objectId = Integer.parseInt(accumulator.toString());
    104                 } else if( qName.equals("last-user") ) {
    105                     fields.lastUserId = Integer.parseInt(accumulator.toString());
    106106                } else if( qName.equals("offset") || qName.equals("calibration-object") ) {
    107107                    // store offset
  • applications/editors/josm/plugins/imagery_offset_db/src/iodb/ImageryOffset.java

    r28008 r29371  
    5757            map.put("maxzoom", String.valueOf(maxZoom));
    5858    }
     59
     60    @Override
     61    public String toString() {
     62        return "ImageryOffset{" + "imageryPos=" + imageryPos + ", imagery=" + imagery + "position=" + position + ", date=" + date + ", author=" + author + ", description=" + description + ", abandonDate=" + abandonDate + '}';
     63    }
    5964}
  • applications/editors/josm/plugins/imagery_offset_db/src/iodb/ImageryOffsetBase.java

    r28008 r29371  
    1212 */
    1313public class ImageryOffsetBase {
    14     private LatLon position;
    15     private Date date;
    16     private String author;
    17     private String description;
    18     private Date abandonDate;
     14    protected long offsetId;
     15    protected LatLon position;
     16    protected Date date;
     17    protected String author;
     18    protected String description;
     19    protected Date abandonDate;
     20    protected String abandonAuthor;
     21    protected String abandonReason;
    1922   
    2023    public void setBasicInfo( LatLon position, String author, String description, Date date ) {
     
    2629    }
    2730
     31    public void setId( long id ) {
     32        this.offsetId = id;
     33    }
     34
     35    public long getId() {
     36        return offsetId;
     37    }
     38
    2839    public void setAbandonDate(Date abandonDate) {
    2940        this.abandonDate = abandonDate;
     
    3344        return abandonDate;
    3445    }
     46
     47    public String getAbandonAuthor() {
     48        return abandonAuthor;
     49    }
     50
     51    public String getAbandonReason() {
     52        return abandonReason;
     53    }
    3554   
    36     public boolean isAbandoned() {
     55    public boolean isDeprecated() {
    3756        return abandonDate != null;
    3857    }
     
    5069    }
    5170
     71    public void setDescription( String description ) {
     72        this.description = description;
     73    }
     74
    5275    public LatLon getPosition() {
    5376        return position;
     
    6083        map.put("description", description);
    6184    }
     85
     86    @Override
     87    public String toString() {
     88        return "ImageryOffsetBase{" + "position=" + position + ", date=" + date + ", author=" + author + ", description=" + description + ", abandonDate=" + abandonDate + '}';
     89    }
    6290}
  • applications/editors/josm/plugins/imagery_offset_db/src/iodb/ImageryOffsetPlugin.java

    r27986 r29371  
    2020        storeAction = new StoreImageryOffsetAction();
    2121       
    22         Main.main.menu.imageryMenu.addSeparator();
    23         Main.main.menu.imageryMenu.add(getAction);
    24         Main.main.menu.imageryMenu.add(storeAction);
    25        
    26         // todo: make MapMode for viewing and updating imagery offsets
     22        // todo: correct menu
     23        Main.main.menu.viewMenu.addSeparator();
     24        Main.main.menu.viewMenu.add(getAction);
     25        Main.main.menu.viewMenu.add(storeAction);
     26
     27        // todo: add a button on toolbar
     28        // todo: make MapMode for viewing and updating imagery offsets (is it needed?)
    2729    }
    2830}
  • applications/editors/josm/plugins/imagery_offset_db/src/iodb/ImageryOffsetTools.java

    r28008 r29371  
    11package iodb;
    22
    3 import java.util.HashMap;
    4 import java.util.List;
     3import java.util.*;
    54import org.openstreetmap.josm.Main;
    65import org.openstreetmap.josm.data.coor.EastNorth;
    76import org.openstreetmap.josm.data.coor.LatLon;
     7import org.openstreetmap.josm.data.imagery.ImageryInfo;
    88import org.openstreetmap.josm.data.projection.Projection;
    99import org.openstreetmap.josm.gui.MapView;
    1010import org.openstreetmap.josm.gui.layer.ImageryLayer;
     11import static org.openstreetmap.josm.tools.I18n.tr;
    1112
    1213/**
     
    1617 */
    1718public class ImageryOffsetTools {
    18     private static HashMap<String, String> imageryAliases;
     19    public static final String DIALOG_TITLE = tr("Imagery Offset");
    1920   
    2021    public static ImageryLayer getTopImageryLayer() {
     22        if( Main.map == null || Main.map.mapView == null )
     23            return null;
    2124        List<ImageryLayer> layers = Main.map.mapView.getLayersOfType(ImageryLayer.class);
    2225        for( ImageryLayer layer : layers ) {
     
    2831    }
    2932   
    30     private static LatLon getMapCenter() {
     33    public static LatLon getMapCenter() {
    3134        Projection proj = Main.getProjection();
    3235        return Main.map == null || Main.map.mapView == null
     
    3740        Projection proj = Main.getProjection();
    3841        EastNorth offsetCenter = proj.latlon2eastNorth(center);
    39         EastNorth centerOffset = offsetCenter.add(layer.getDx(), layer.getDy()); // todo: add or substract?
     42        EastNorth centerOffset = offsetCenter.add(-layer.getDx(), -layer.getDy()); // todo: add or substract?
    4043        LatLon offsetLL = proj.eastNorth2latlon(centerOffset);
    4144        return offsetLL;
     
    4649        EastNorth center = proj.latlon2eastNorth(offset.getPosition());
    4750        EastNorth offsetPos = proj.latlon2eastNorth(offset.getImageryPos());
    48         layer.setOffset(offsetPos.getX() - center.getX(), offsetPos.getY() - center.getY()); // todo: + or -?
     51        layer.setOffset(center.getX() - offsetPos.getX(), center.getY() - offsetPos.getY());
    4952    }
    5053   
     
    5760            return null;
    5861       
    59         if( imageryAliases == null )
    60             loadImageryAliases();
    61         for( String substr : imageryAliases.keySet() )
    62             if( url.contains(substr) )
    63                 return imageryAliases.get(substr);
    64        
    65         return url; // todo: strip parametric parts, etc
    66     }
    67    
    68     private static void loadImageryAliases() {
    69         if( imageryAliases == null )
    70             imageryAliases = new HashMap<String, String>();
    71         else
    72             imageryAliases.clear();
    73        
    74         // { substring, alias }
    75         imageryAliases.put("bing", "bing");
    76         // todo: load from a resource?
     62        // predefined layers
     63        if( layer.getInfo().getImageryType().equals(ImageryInfo.ImageryType.BING) || url.contains("tiles.virtualearth.net") )
     64            return "bing";
     65
     66        if( layer.getInfo().getImageryType().equals(ImageryInfo.ImageryType.SCANEX) && url.toLowerCase().equals("irs") )
     67            return "scanex_irs";
     68
     69        boolean isWMS = layer.getInfo().getImageryType().equals(ImageryInfo.ImageryType.WMS);
     70
     71        System.out.println(url);
     72
     73        // Remove protocol
     74        int i = url.indexOf("://");
     75        url = url.substring(i + 3);
     76
     77        // Split URL into address and query string
     78        i = url.indexOf('?');
     79        String query = "";
     80        if( i > 0 ) {
     81            query = url.substring(i);
     82            url = url.substring(0, i);
     83        }
     84
     85        // Parse query parameters into a sorted map
     86        Map<String, String> qparams = new TreeMap<String, String>();
     87        String[] qparamsStr = query.length() > 1 ? query.substring(1).split("&") : new String[0];
     88        for( String param : qparamsStr ) {
     89            String[] kv = param.split("=");
     90            kv[0] = kv[0].toLowerCase();
     91            // WMS: if this is WMS, remove all parameters except map and layers
     92            if( isWMS && !(kv[0].equals("map") || kv[0].equals("layers")) )
     93                continue;
     94            // TMS: skip parameters with variable values
     95            if( kv.length > 1 && kv[1].indexOf('{') >= 0 && kv[1].indexOf('}') > 0 )
     96                continue;
     97            qparams.put(kv[0].toLowerCase(), kv.length > 1 ? kv[1] : null);
     98        }
     99
     100        // Reconstruct query parameters
     101        StringBuilder sb = new StringBuilder();
     102        for( String qk : qparams.keySet() ) {
     103            if( sb.length() > 0 )
     104                sb.append('&');
     105            else if( query.length() > 0 )
     106                sb.append('?');
     107            sb.append(qk).append('=').append(qparams.get(qk));
     108        }
     109        query = sb.toString();
     110
     111        // TMS: remove /{zoom} and /{y}.png parts
     112        url = url.replaceAll("\\/\\{[^}]+\\}(?:\\.\\w+)?", "");
     113        // TMS: remove variable parts
     114        url = url.replaceAll("\\{[^}]+\\}", "");
     115        while( url.contains("..") )
     116            url = url.replace("..", ".");
     117        if( url.startsWith(".") )
     118            url = url.substring(1);
     119
     120        System.out.println("-> " + url + query);
     121        return url + query;
    77122    }
    78123   
     
    110155        return intResult;
    111156    }
     157
     158    public static String getServerURL() {
     159        return Main.pref.get("iodb.server.url", "http://offsets.textual.ru/");
     160    }
    112161}
  • applications/editors/josm/plugins/imagery_offset_db/src/iodb/OffsetDialog.java

    r28008 r29371  
    2929            OffsetDialogButton button = new OffsetDialogButton(offset);
    3030            button.addActionListener(this);
     31/*            JPopupMenu popupMenu = new JPopupMenu();
     32            popupMenu.add(new OffsetInfoAction(offset));
     33            if( !offset.isDeprecated() )
     34                popupMenu.add(new DeprecateOffsetAction(offset));
     35            button.add(popupMenu);*/
    3136            buttonPanel.add(button);
    3237        }
     38        // todo: calibration objects and deprecated offsets button
    3339        JButton cancelButton = new JButton("Cancel");
    3440        cancelButton.addActionListener(this);
  • applications/editors/josm/plugins/imagery_offset_db/src/iodb/OffsetDialogButton.java

    r28008 r29371  
    1313
    1414    public OffsetDialogButton( ImageryOffsetBase offset ) {
    15         super(offset.getDescription() + " (" + offset.getPosition().lat() + ", " + offset.getPosition().lon() + ")");
     15        super(offset.getDescription() + " (" + Math.round(offset.getPosition().greatCircleDistance(ImageryOffsetTools.getMapCenter())) + " m)");
    1616        this.offset = offset;
    1717    }
  • applications/editors/josm/plugins/imagery_offset_db/src/iodb/OffsetInfoAction.java

    r29361 r29371  
    22
    33import java.awt.event.ActionEvent;
    4 import java.awt.event.KeyEvent;
    5 import java.io.IOException;
    6 import java.io.InputStream;
    7 import java.io.UnsupportedEncodingException;
    8 import java.net.*;
    9 import java.util.ArrayList;
    10 import java.util.Collections;
    11 import java.util.HashMap;
    12 import java.util.List;
    13 import java.util.concurrent.Future;
    14 import java.util.logging.Level;
    15 import java.util.logging.Logger;
    16 import org.openstreetmap.gui.jmapviewer.tilesources.AbstractTMSTileSource;
     4import javax.swing.AbstractAction;
     5import javax.swing.JOptionPane;
    176import org.openstreetmap.josm.Main;
    18 import org.openstreetmap.josm.actions.JosmAction;
    19 import org.openstreetmap.josm.data.coor.LatLon;
    20 import org.openstreetmap.josm.data.projection.Projection;
    21 import org.openstreetmap.josm.gui.MapView;
    22 import org.openstreetmap.josm.gui.PleaseWaitRunnable;
    23 import org.openstreetmap.josm.gui.layer.ImageryLayer;
    24 import org.openstreetmap.josm.gui.progress.ProgressMonitor;
    25 import org.openstreetmap.josm.io.OsmTransferException;
    267import static org.openstreetmap.josm.tools.I18n.tr;
    27 import org.openstreetmap.josm.tools.Shortcut;
    28 import org.xml.sax.SAXException;
     8import org.openstreetmap.josm.tools.ImageProvider;
    299
    3010/**
     
    3313 * @author zverik
    3414 */
    35 public class GetImageryOffsetAction extends JosmAction {
     15public class OffsetInfoAction extends AbstractAction {
     16    private ImageryOffsetBase offset;
    3617   
    37     private List<ImageryOffsetBase> offsets;
    38    
    39     public GetImageryOffsetAction() {
    40         super(tr("Get Imagery Offset..."), "getoffset", tr("Download offsets for current imagery from a server"),
    41                 Shortcut.registerShortcut("imageryoffset:get", tr("Imagery: {0}", tr("Get Imagery Offset...")), KeyEvent.VK_I, Shortcut.ALT+Shortcut.CTRL), true);
    42         offsets = Collections.emptyList();
     18    public OffsetInfoAction( ImageryOffsetBase offset ) {
     19        super(tr("Offset Information"));
     20        putValue(SMALL_ICON, ImageProvider.get("dialogs", "delete"));
     21        this.offset = offset;
     22        setEnabled(offset != null);
    4323    }
    4424
    4525    public void actionPerformed(ActionEvent e) {
    46         Projection proj = Main.map.mapView.getProjection();
    47         LatLon center = proj.eastNorth2latlon(Main.map.mapView.getCenter());
    48         ImageryLayer layer = ImageryOffsetTools.getTopImageryLayer();
    49         String imagery = ImageryOffsetTools.getImageryID(layer);
    50         if( imagery == null )
    51             return;
    52        
    53         List<ImageryOffsetBase> offsets = download(center, imagery); // todo: async
    54         /*DownloadOffsets download = new DownloadOffsets();
    55         Future<?> future = Main.worker.submit(download);
    56         try {
    57             future.get();
    58         } catch( Exception ex ) {
    59             ex.printStackTrace();
    60             return;
    61         }*/
    62        
    63         // todo: show a dialog for selecting one of the offsets (without "update" flag)
    64         ImageryOffsetBase offset = new OffsetDialog(offsets).showDialog();
    65         if( offset != null ) {
    66             // todo: use the chosen offset
    67             if( offset instanceof ImageryOffset ) {
    68                 ImageryOffsetTools.applyLayerOffset(layer, (ImageryOffset)offset);
    69             } else if( offset instanceof CalibrationObject ) {
    70                 // todo: select object
    71             }
    72         }
    73     }
    74    
    75     private List<ImageryOffsetBase> download( LatLon center, String imagery ) {
    76         String base = Main.pref.get("iodb.server.url", "http://offsets.textual.ru/");
    77         String query = "get?lat=" + center.getX() + "&lon=" + center.getY();
    78         List<ImageryOffsetBase> result = null;
    79         try {
    80             query = query + "&imagery=" + URLEncoder.encode(imagery, "utf-8");
    81             URL url = new URL(base + query);
    82             System.out.println("url=" + url);
    83             HttpURLConnection connection = (HttpURLConnection)url.openConnection();
    84             connection.connect();
    85             int retCode = connection.getResponseCode();
    86             InputStream inp = connection.getInputStream();
    87             if( inp != null ) {
    88                 result = new IODBReader(inp).parse();
    89                 System.out.println("result.size() = " + result.size());
    90             }
    91             connection.disconnect();
    92         } catch( MalformedURLException ex ) {
    93             // ?
    94         } catch( UnsupportedEncodingException e ) {
    95             // do nothing. WTF is that?
    96         } catch( IOException e ) {
    97             e.printStackTrace();
    98             // ?
    99         } catch( SAXException e ) {
    100             e.printStackTrace();
    101             // ?
    102         }
    103         if( result == null )
    104             result = new ArrayList<ImageryOffsetBase>();
    105         return result;
    106     }
    107    
    108     class DownloadOffsets extends PleaseWaitRunnable {
    109        
    110         private boolean cancelled;
    111 
    112         public DownloadOffsets() {
    113             super(tr("Downloading calibration data"));
    114             cancelled = false;
    115         }
    116 
    117         @Override
    118         protected void realRun() throws SAXException, IOException, OsmTransferException {
    119             // todo: open httpconnection to server and read xml
    120             if( cancelled )
    121                 return;
    122            
    123         }
    124 
    125         @Override
    126         protected void finish() {
    127             if( cancelled )
    128                 return;
    129             // todo: parse xml and return an array of ImageryOffsetBase
    130         }
    131        
    132         @Override
    133         protected void cancel() {
    134             cancelled = true;
    135         }
     26        JOptionPane.showMessageDialog(Main.parent, "TODO", ImageryOffsetTools.DIALOG_TITLE, JOptionPane.PLAIN_MESSAGE);
    13627    }
    13728}
  • applications/editors/josm/plugins/imagery_offset_db/src/iodb/StoreImageryOffsetAction.java

    r28008 r29371  
    22
    33import java.awt.event.ActionEvent;
    4 import java.util.HashMap;
    5 import java.util.Map;
     4import java.io.UnsupportedEncodingException;
     5import java.net.*;
     6import java.util.*;
     7import javax.swing.JOptionPane;
    68import org.openstreetmap.josm.Main;
    79import org.openstreetmap.josm.actions.JosmAction;
    810import org.openstreetmap.josm.data.coor.LatLon;
    9 import org.openstreetmap.josm.data.projection.Projection;
     11import org.openstreetmap.josm.data.osm.*;
     12import org.openstreetmap.josm.gui.JosmUserIdentityManager;
     13import org.openstreetmap.josm.gui.layer.ImageryLayer;
    1014import static org.openstreetmap.josm.tools.I18n.tr;
    1115
     
    1822
    1923    public StoreImageryOffsetAction() {
    20         super(tr("Store Imagery Offset..."), "storeoffset", tr("Upload an offset for current imagery (or calibration object information) to a server"), null, false);
     24        super(tr("Store Imagery Offset..."), "storeoffset",
     25                tr("Upload an offset for current imagery (or calibration object information) to a server"),
     26                null, false);
    2127    }
    2228
    2329    public void actionPerformed(ActionEvent e) {
    24         // todo: check that there is an imagery
    25         // and that it is moved
    26         Projection proj = Main.map.mapView.getProjection();
    27         LatLon center = proj.eastNorth2latlon(Main.map.mapView.getCenter());
    28         // todo: open an upload window
    29         // todo: if an object was selected, ask if the user wants to upload it
    30         // todo: enter all metadata (that is, a description)
    31         // todo: upload object info to server
     30        if( Main.map == null || Main.map.mapView == null || getCurrentDataSet() == null )
     31            return;
     32
     33        ImageryLayer layer = ImageryOffsetTools.getTopImageryLayer();
     34        if( layer == null )
     35            return;
     36
     37        String userName = JosmUserIdentityManager.getInstance().getUserName();
     38        if( userName == null ) {
     39            JOptionPane.showMessageDialog(Main.parent, tr("To store imagery offsets you must be a registered OSM user."), ImageryOffsetTools.DIALOG_TITLE, JOptionPane.ERROR_MESSAGE);
     40            return;
     41        }
     42           
     43        // check if an object suitable for calibration is selected
     44        OsmPrimitive calibration = null;
     45        Collection<OsmPrimitive> selectedObjects = getCurrentDataSet().getSelected();
     46        if( selectedObjects.size() == 1 ) {
     47            OsmPrimitive selection = selectedObjects.iterator().next();
     48            if( selection instanceof Node || selection instanceof Way ) {
     49                boolean suitable = !selection.isNewOrUndeleted() && !selection.isDeleted() && !selection.isModified();
     50                if( selection instanceof Way ) {
     51                    for( Node n : ((Way)selection).getNodes() )
     52                        if( n.isNewOrUndeleted() || n.isDeleted() || n.isModified() )
     53                            suitable = false;
     54                } else if( selection.isReferredByWays(1) ) {
     55                    suitable = false;
     56                }
     57                if( suitable ) {
     58                    String[] options = new String[] {tr("Store calibration object"), tr("Store imagery offset"), tr("Cancel")};
     59                    int result = JOptionPane.showOptionDialog(Main.parent,
     60                            tr("The selected object can be used as a calibration object. What do you intend to do?"), ImageryOffsetTools.DIALOG_TITLE, JOptionPane.DEFAULT_OPTION, JOptionPane.QUESTION_MESSAGE,
     61                            null, options, options[0]);
     62                    if( result == 2 || result == JOptionPane.CLOSED_OPTION )
     63                        return;
     64                    if( result == 0 )
     65                        calibration = selection;
     66                } else {
     67                    String[] options = new String[] {tr("Store imagery offset"), tr("Cancel")};
     68                    int result = JOptionPane.showOptionDialog(Main.parent,
     69                            tr("You have an object selected and might want to use it as a calibration object.\n"
     70                             + "But in this case it should be uploaded to OSM server first."), ImageryOffsetTools.DIALOG_TITLE, JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE,
     71                            null, options, options[1]);
     72                    if( result == 1 || result == JOptionPane.CLOSED_OPTION )
     73                        return;
     74                }
     75            }
     76        }
     77
     78        Object message = "";
     79        LatLon center = ImageryOffsetTools.getMapCenter();
     80        ImageryOffsetBase offsetObj;
     81        if( calibration == null ) {
     82            // register imagery offset
     83            if( Math.abs(layer.getDx()) < 1e-8 && Math.abs(layer.getDy()) < 1e-8 ) {
     84                if( JOptionPane.showConfirmDialog(Main.parent,
     85                        tr("The topmost imagery layer has no offset. Are you sure you want to upload it?"), ImageryOffsetTools.DIALOG_TITLE, JOptionPane.YES_NO_OPTION) != JOptionPane.YES_OPTION )
     86                    return;
     87            }
     88            LatLon offset = ImageryOffsetTools.getLayerOffset(layer, center);
     89            offsetObj = new ImageryOffset(ImageryOffsetTools.getImageryID(layer), offset);
     90            message = "You are registering an imagery offset.\n"
     91                    + "Other users in this area will be able to use it for mapping.\n"
     92                    + "Please make sure it is as precise as possible, and\n"
     93                    + "describe a region this offset is applicable to.";
     94        } else {
     95            // register calibration object
     96            offsetObj = new CalibrationObject(calibration);
     97            message = "You are registering calibration object.\n"
     98                    + "It should be the most precisely positioned object,\n"
     99                    + "with clearly visible boundaries on various satellite imagery.\n"
     100                    + "Please describe a region where this object is located.";
     101        }
     102        offsetObj.setBasicInfo(center, userName, null, null);
     103        String description = null;
     104        boolean iterated = false;
     105        while( description == null ) {
     106            description = JOptionPane.showInputDialog(Main.parent, message, ImageryOffsetTools.DIALOG_TITLE, JOptionPane.PLAIN_MESSAGE);
     107            if( description == null || description.length() == 0 )
     108                return;
     109            if( description.length() < 3 || description.length() > 200 ) {
     110                description = null;
     111                if( !iterated ) {
     112                    message = message + "\n" + tr("Description should be 3 to 200 letters long.");
     113                    iterated = true;
     114                }
     115            }
     116        }
     117        offsetObj.setDescription(description);
     118
     119        // upload object info to server
     120        try {
     121            Map<String, String> params = new HashMap<String, String>();
     122            offsetObj.putServerParams(params);
     123            StringBuilder query = null;
     124            for( String key : params.keySet() ) {
     125                if( query == null ) {
     126                    query = new StringBuilder("store?");
     127                } else {
     128                    query.append('&');
     129                }
     130                query.append(key).append('=').append(URLEncoder.encode(params.get(key), "UTF8"));
     131            }
     132            Main.main.worker.submit(new SimpleOffsetQueryTask(query.toString(), tr("Uploading the new offset...")));
     133        } catch( UnsupportedEncodingException ex ) {
     134            // WTF
     135        }
    32136    }
    33    
    34     private static void upload( ImageryOffsetBase offset ) {
    35         String base = Main.pref.get("iodb.server.url", "http://offsets.textual.ru/");
    36         Map<String, String> params = new HashMap<String, String>();
    37         offset.putServerParams(params);
    38         // todo
     137
     138    @Override
     139    protected void updateEnabledState() {
     140        boolean state = true;
     141        if( Main.map == null || Main.map.mapView == null || !Main.map.isVisible() )
     142            state = false;
     143        if( ImageryOffsetTools.getTopImageryLayer() == null )
     144            state = false;
     145        setEnabled(state);
    39146    }
    40147}
Note: See TracChangeset for help on using the changeset viewer.