Index: /applications/editors/josm/plugins/imagery_offset_db/src/iodb/CalibrationLayer.java
===================================================================
--- /applications/editors/josm/plugins/imagery_offset_db/src/iodb/CalibrationLayer.java	(revision 29376)
+++ /applications/editors/josm/plugins/imagery_offset_db/src/iodb/CalibrationLayer.java	(revision 29376)
@@ -0,0 +1,192 @@
+package iodb;
+
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.geom.GeneralPath;
+import javax.swing.*;
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.actions.AutoScaleAction;
+import org.openstreetmap.josm.data.Bounds;
+import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
+import org.openstreetmap.josm.gui.MapView;
+import org.openstreetmap.josm.gui.dialogs.LayerListDialog;
+import org.openstreetmap.josm.gui.dialogs.LayerListPopup;
+import org.openstreetmap.josm.gui.layer.Layer;
+import static org.openstreetmap.josm.tools.I18n.tr;
+import org.openstreetmap.josm.tools.ImageProvider;
+
+/**
+ * A layer that displays calibration geometry for an offset.
+ *
+ * @author zverik
+ */
+public class CalibrationLayer extends Layer {
+    private Color color;
+    private Icon icon;
+    private CalibrationObject obj;
+    private LatLon center;
+
+    public CalibrationLayer( CalibrationObject obj ) {
+        super(tr("Calibration Layer"));
+        color = Color.RED;
+        this.obj = obj;
+    }
+
+    @Override
+    public void paint( Graphics2D g, MapView mv, Bounds box ) {
+        Stroke oldStroke = g.getStroke();
+        g.setColor(color);
+        g.setStroke(new BasicStroke(1));
+        LatLon[] geometry = obj.getGeometry();
+        if( geometry.length == 1 ) {
+            // draw crosshair
+            Point p = mv.getPoint(geometry[0]);
+            g.drawLine(p.x, p.y, p.x, p.y);
+            g.drawLine(p.x - 10, p.y, p.x - 20, p.y);
+            g.drawLine(p.x + 10, p.y, p.x + 20, p.y);
+            g.drawLine(p.x, p.y - 10, p.x, p.y - 20);
+            g.drawLine(p.x, p.y + 10, p.x, p.y + 20);
+        } else if( geometry.length > 1 ) {
+            // draw a line
+            GeneralPath path = new GeneralPath();
+            for( int i = 0; i < geometry.length; i++ ) {
+                Point p = mv.getPoint(geometry[i]);
+                if( i == 0 )
+                    path.moveTo(p.x, p.y);
+                else
+                    path.lineTo(p.x, p.y);
+            }
+            g.draw(path);
+        }
+        g.setStroke(oldStroke);
+    }
+
+    @Override
+    public Icon getIcon() {
+        if( icon == null )
+            icon = ImageProvider.get("calibration_layer");
+        return icon;
+    }
+
+    @Override
+    public void mergeFrom( Layer from ) {
+    }
+
+    @Override
+    public boolean isMergable( Layer other ) {
+        return false;
+    }
+
+    @Override
+    public void visitBoundingBox( BoundingXYVisitor v ) {
+        for( LatLon ll : obj.getGeometry() )
+            v.visit(ll);
+    }
+
+    @Override
+    public String getToolTipText() {
+        return "A calibration " + getGeometryType() + " by " + obj.getAuthor();
+    }
+
+    @Override
+    public Object getInfoComponent() {
+        String info = "A calibration " + getGeometryType() + "\n"
+                + "Created by " + obj.getAuthor() + " on " + ImageryOffsetTools.DATE_FORMAT.format(obj.getDate()) + "\n"
+                + "Description: " + obj.getDescription();
+        if( obj.isDeprecated() ) {
+            info += "\nThis geometry was marked obsolete\n"
+                    + "by " + obj.getAbandonAuthor() + " on " + ImageryOffsetTools.DATE_FORMAT.format(obj.getAbandonDate()) + "\n"
+                    + "Reason: " + obj.getAbandonReason();
+        }
+        return info;
+    }
+
+    private String getGeometryType() {
+        int n = obj.getGeometry().length;
+        if( n == 1 )
+            return "point";
+        else if( n > 1 && !obj.getGeometry()[0].equals(obj.getGeometry()[n-1]) )
+            return "path";
+        else if( n > 1 && obj.getGeometry()[0].equals(obj.getGeometry()[n-1]) )
+            return "polygon";
+        else
+            return "geometry";
+    }
+
+    @Override
+    public Action[] getMenuEntries() {
+        return new Action[] {
+            LayerListDialog.getInstance().createShowHideLayerAction(),
+            LayerListDialog.getInstance().createDeleteLayerAction(),
+            SeparatorLayerAction.INSTANCE,
+            new ZoomToLayerAction(),
+            new SelectColorAction(Color.RED),
+            new SelectColorAction(Color.CYAN),
+            new SelectColorAction(Color.YELLOW),
+            SeparatorLayerAction.INSTANCE,
+            new LayerListPopup.InfoAction(this)
+        };
+    }
+
+    public void panToCenter() {
+        if( center == null ) {
+            LatLon[] geometry = obj.getGeometry();
+            double lat = 0.0;
+            double lon = 0.0;
+            for( int i = 0; i < geometry.length; i++ ) {
+                lon += geometry[i].lon();
+                lat += geometry[i].lat();
+            }
+            center = new LatLon(lat / geometry.length, lon / geometry.length);
+        }
+        Main.map.mapView.zoomTo(center);
+    }
+
+    class SelectColorAction extends AbstractAction {
+        private Color c;
+
+        public SelectColorAction( Color color ) {
+            super(tr("Change Color"));
+            putValue(SMALL_ICON, new SingleColorIcon(color));
+            this.c = color;
+        }
+
+        public void actionPerformed( ActionEvent e ) {
+            color = c;
+            Main.map.mapView.repaint();
+        }
+    }
+
+    class SingleColorIcon implements Icon {
+        private Color color;
+
+        public SingleColorIcon( Color color ) {
+            this.color = color;
+        }
+
+        public void paintIcon( Component c, Graphics g, int x, int y ) {
+            g.setColor(color);
+            g.fillRect(x, y, 24, 24);
+        }
+
+        public int getIconWidth() {
+            return 24;
+        }
+
+        public int getIconHeight() {
+            return 24;
+        }
+
+    }
+
+    class ZoomToLayerAction extends AbstractAction {
+        public ZoomToLayerAction() {
+            super(tr("Zoom to layer"));
+        }
+
+        public void actionPerformed( ActionEvent e ) {
+            AutoScaleAction.autoScale("layer");
+        }
+    }
+}
Index: /applications/editors/josm/plugins/imagery_offset_db/src/iodb/CalibrationObject.java
===================================================================
--- /applications/editors/josm/plugins/imagery_offset_db/src/iodb/CalibrationObject.java	(revision 29375)
+++ /applications/editors/josm/plugins/imagery_offset_db/src/iodb/CalibrationObject.java	(revision 29376)
@@ -2,5 +2,8 @@
 
 import java.util.Map;
-import org.openstreetmap.josm.data.osm.*;
+import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.data.osm.Node;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.data.osm.Way;
 
 /**
@@ -9,34 +12,40 @@
  */
 public class CalibrationObject extends ImageryOffsetBase {
-    private OsmPrimitive object;
-    private long lastUserId;
+    private LatLon[] geometry;
 
-    public CalibrationObject(OsmPrimitive object, long lastUserId) {
-        this.object = object;
-        this.lastUserId = lastUserId;
+    public CalibrationObject(LatLon[] geometry) {
+        this.geometry = geometry;
     }
 
-    public CalibrationObject(OsmPrimitive object) {
-        this(object, 0);
+    public CalibrationObject( OsmPrimitive p ) {
+        if( p instanceof Node )
+            geometry = new LatLon[] { ((Node)p).getCoor() };
+        else if( p instanceof Way ) {
+            geometry = new LatLon[((Way)p).getNodesCount()];
+            for( int i = 0; i < geometry.length; i++ )
+                geometry[i] = ((Way)p).getNode(i).getCoor();
+        } else
+            throw new IllegalArgumentException("Calibration Object can be created either from node or a way");
     }
 
-    public long getLastUserId() {
-        return lastUserId;
+    public LatLon[] getGeometry() {
+        return geometry;
     }
 
-    public OsmPrimitive getObject() {
-        return object;
-    }
-    
     @Override
     public void putServerParams( Map<String, String> map ) {
         super.putServerParams(map);
-        map.put("object", object instanceof Node ? "node" : "way");
-        map.put("id", String.valueOf(object.getId()));
+        StringBuilder sb = new StringBuilder();
+        for( int i = 0; i < geometry.length; i++ ) {
+            if( i > 0 )
+                sb.append(',');
+            sb.append(geometry[i].lon()).append(' ').append(geometry[i].lat());
+        }
+        map.put("geometry", sb.toString());
     }
 
     @Override
     public String toString() {
-        return "CalibrationObject{" + "object=" + object + ", lastUserId=" + lastUserId + "position=" + position + ", date=" + date + ", author=" + author + ", description=" + description + ", abandonDate=" + abandonDate + '}';
+        return "CalibrationObject{" + geometry.length + "nodes; position=" + position + ", date=" + date + ", author=" + author + ", description=" + description + ", abandonDate=" + abandonDate + '}';
     }
 }
Index: /applications/editors/josm/plugins/imagery_offset_db/src/iodb/GetImageryOffsetAction.java
===================================================================
--- /applications/editors/josm/plugins/imagery_offset_db/src/iodb/GetImageryOffsetAction.java	(revision 29375)
+++ /applications/editors/josm/plugins/imagery_offset_db/src/iodb/GetImageryOffsetAction.java	(revision 29376)
@@ -9,9 +9,6 @@
 import javax.swing.JOptionPane;
 import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.actions.AutoScaleAction;
-import org.openstreetmap.josm.actions.DownloadPrimitiveAction;
 import org.openstreetmap.josm.actions.JosmAction;
 import org.openstreetmap.josm.data.coor.LatLon;
-import org.openstreetmap.josm.data.osm.*;
 import org.openstreetmap.josm.data.projection.Projection;
 import org.openstreetmap.josm.gui.layer.ImageryLayer;
@@ -70,63 +67,18 @@
                 Main.map.repaint();
             } else if( offset instanceof CalibrationObject ) {
-                OsmPrimitive obj = ((CalibrationObject)offset).getObject();
-                final List<PrimitiveId> ids = new ArrayList<PrimitiveId>(1);
-                ids.add(obj);
-                DownloadPrimitiveAction.processItems(false, ids, false, true);
-                Main.worker.submit(new AfterCalibrationDownloadTask((CalibrationObject)offset));
+                CalibrationLayer clayer = new CalibrationLayer((CalibrationObject)offset);
+                Main.map.mapView.addLayer(clayer);
+                clayer.panToCenter();
+                if( !Main.pref.getBoolean("iodb.calibration.message", false) ) {
+                    JOptionPane.showMessageDialog(Main.parent, // todo: update text
+                            tr("A layer has been added with a calibration geometry. Hide data layers,\n"
+                            + "find the corresponding feature on the imagery layer and move it accordingly."),
+                            ImageryOffsetTools.DIALOG_TITLE, JOptionPane.INFORMATION_MESSAGE);
+                    Main.pref.put("iodb.calibration.message", true);
+                }
             }
         }
     }
 
-    class AfterCalibrationDownloadTask implements Runnable {
-        private CalibrationObject offset;
-
-        public AfterCalibrationDownloadTask( CalibrationObject offset ) {
-            this.offset = offset;
-        }
-
-        @Override
-        public void run() {
-            OsmPrimitive p = getCurrentDataSet().getPrimitiveById(offset.getObject());
-            if( p == null ) {
-                return;
-            }
-            // check for last user
-            if( offset.getLastUserId() > 0 ) {
-                long uid = p.getUser().getId();
-                Date ts = p.getTimestamp();
-                if( p instanceof Way ) {
-                    for( Node n : ((Way)p).getNodes() ) {
-                        if( n.getTimestamp().after(ts) ) {
-                            ts = n.getTimestamp();
-                            uid = n.getUser().getId();
-                        }
-                    }
-                }
-                if( uid != offset.getLastUserId() ) {
-                    int result = JOptionPane.showConfirmDialog(Main.parent,
-                            tr("The calibration object has been changed in unknown way.\n"
-                             + "It may be moved or extended, thus ceasing to be a reliable mark\n"
-                             + "for imagery calibration. Do you want to notify the server of this?"),
-                            ImageryOffsetTools.DIALOG_TITLE, JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
-                    if( result == JOptionPane.YES_OPTION ) {
-                        DeprecateOffsetAction.deprecateOffset(offset);
-                        return;
-                    }
-                }
-            }
-            Main.main.getCurrentDataSet().setSelected(p);
-            AutoScaleAction.zoomTo(Collections.singleton(p));
-            if( !Main.pref.getBoolean("iodb.calibration.message", false) ) {
-                JOptionPane.showMessageDialog(Main.parent,
-                        tr("An object has been selected on the map. Find the corresponding feature\n"
-                         + "on the imagery layer and move that layer accordingly.\n"
-                         + "DO NOT touch the selected object, so it can be used by others later."),
-                        ImageryOffsetTools.DIALOG_TITLE, JOptionPane.INFORMATION_MESSAGE);
-                Main.pref.put("iodb.calibration.message", true);
-            }
-        }
-    }
-    
     class DownloadOffsetsTask extends SimpleOffsetQueryTask {
         private ImageryLayer layer;
@@ -138,4 +90,7 @@
                 String query = "get?lat=" + center.lat() + "&lon=" + center.lon()
                         + "&imagery=" + URLEncoder.encode(imagery, "UTF8");
+                int radius = Main.pref.getInteger("iodb.radius", -1);
+                if( radius > 0 )
+                    query = query + "?radius=" + radius;
                 setQuery(query);
             } catch( UnsupportedEncodingException e ) {
Index: /applications/editors/josm/plugins/imagery_offset_db/src/iodb/IODBReader.java
===================================================================
--- /applications/editors/josm/plugins/imagery_offset_db/src/iodb/IODBReader.java	(revision 29375)
+++ /applications/editors/josm/plugins/imagery_offset_db/src/iodb/IODBReader.java	(revision 29376)
@@ -11,7 +11,4 @@
 import javax.xml.parsers.SAXParserFactory;
 import org.openstreetmap.josm.data.coor.LatLon;
-import org.openstreetmap.josm.data.osm.Node;
-import org.openstreetmap.josm.data.osm.OsmPrimitive;
-import org.openstreetmap.josm.data.osm.Way;
 import org.openstreetmap.josm.io.UTFInputStreamReader;
 import org.xml.sax.Attributes;
@@ -33,4 +30,5 @@
         private IOFields fields;
         private boolean parsingOffset;
+        private boolean parsingDeprecate;
         private SimpleDateFormat dateParser = new SimpleDateFormat("yyyy-MM-dd");
 
@@ -51,14 +49,14 @@
         public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
             if( !parsingOffset ) {
-                if( qName.equals("offset") || qName.equals("calibration-object") ) {
+                if( qName.equals("offset") || qName.equals("calibration") ) {
                     parsingOffset = true;
+                    parsingDeprecate = false;
                     fields.clear();
                     fields.position = parseLatLon(attributes);
+                    fields.id = Integer.parseInt(attributes.getValue("id"));
                 }
             } else {
-                if( qName.equals("object") ) {
-                    fields.isNode = attributes.getValue("type").equals("node");
-                } else if( qName.equals("last-user") ) {
-                    fields.lastUserId = Integer.parseInt(attributes.getValue("id"));
+                if( qName.equals("node") ) {
+                    fields.geometry.add(parseLatLon(attributes));
                 } else if( qName.equals("imagery-position") ) {
                     fields.imageryPos = parseLatLon(attributes);
@@ -70,4 +68,6 @@
                     if( maxZoom != null )
                         fields.maxZoom = Integer.parseInt(maxZoom);
+                } else if( qName.equals("deprecated") ) {
+                    parsingDeprecate = true;
                 }
             }
@@ -85,24 +85,26 @@
             if( parsingOffset ) {
                 if( qName.equals("author") ) {
-                    fields.author = accumulator.toString();
+                    if( !parsingDeprecate )
+                        fields.author = accumulator.toString();
+                    else
+                        fields.abandonAuthor = accumulator.toString();
                 } else if( qName.equals("description") ) {
                     fields.description = accumulator.toString();
+                } else if( qName.equals("reason") && parsingDeprecate ) {
+                    fields.abandonReason = accumulator.toString();
                 } else if( qName.equals("date") ) {
                     try {
-                        fields.date = dateParser.parse(accumulator.toString());
+                        if( !parsingDeprecate )
+                            fields.date = dateParser.parse(accumulator.toString());
+                        else
+                            fields.abandonDate = dateParser.parse(accumulator.toString());
                     } catch (ParseException ex) {
                         throw new SAXException(ex);
                     }
                 } else if( qName.equals("deprecated") ) {
-                    try {
-                        fields.abandonDate = dateParser.parse(accumulator.toString());
-                    } catch (ParseException ex) {
-                        throw new SAXException(ex);
-                    }
+                    parsingDeprecate = false;
                 } else if( qName.equals("imagery") ) {
                     fields.imagery = accumulator.toString();
-                } else if( qName.equals("object") ) {
-                    fields.objectId = Integer.parseInt(accumulator.toString());
-                } else if( qName.equals("offset") || qName.equals("calibration-object") ) {
+                } else if( qName.equals("offset") || qName.equals("calibration") ) {
                     // store offset
                     try {
@@ -136,4 +138,5 @@
     
     private class IOFields {
+        public int id;
         public LatLon position;
         public Date date;
@@ -141,10 +144,10 @@
         public String description;
         public Date abandonDate;
+        public String abandonAuthor;
+        public String abandonReason;
         public LatLon imageryPos;
         public String imagery;
         public int minZoom, maxZoom;
-        public boolean isNode;
-        public long objectId;
-        public long lastUserId;
+        public List<LatLon> geometry;
 
         public IOFields() {
@@ -153,4 +156,5 @@
         
         public void clear() {
+            id = -1;
             position = null;
             date = null;
@@ -158,11 +162,11 @@
             description = null;
             abandonDate = null;
+            abandonAuthor = null;
+            abandonReason = null;
             imageryPos = null;
             imagery = null;
             minZoom = -1;
             maxZoom = -1;
-            isNode = false;
-            objectId = -1;
-            lastUserId = -1;
+            geometry = new ArrayList<LatLon>();
         }
 
@@ -170,22 +174,21 @@
             if( author == null || description == null || position == null || date == null )
                 throw new IllegalArgumentException("Not enought arguments to build an object");
-            if( objectId < 0 ) {
+            ImageryOffsetBase result;
+            if( geometry.isEmpty() ) {
                 if( imagery == null || imageryPos == null )
                     throw new IllegalArgumentException("Both imagery and imageryPos should be sepcified for the offset");
-                ImageryOffset result = new ImageryOffset(imagery, imageryPos);
+                result = new ImageryOffset(imagery, imageryPos);
                 if( minZoom >= 0 )
-                    result.setMinZoom(minZoom);
+                    ((ImageryOffset)result).setMinZoom(minZoom);
                 if( maxZoom >= 0 )
-                    result.setMaxZoom(maxZoom);
-                result.setBasicInfo(position, author, description, date);
-                result.setAbandonDate(abandonDate);
-                return result;
+                    ((ImageryOffset)result).setMaxZoom(maxZoom);
             } else {
-                OsmPrimitive p = isNode ? new Node(objectId) : new Way(objectId);
-                CalibrationObject result = new CalibrationObject(p, lastUserId);
-                result.setBasicInfo(position, author, description, date);
-                result.setAbandonDate(abandonDate);
-                return result;
+                result = new CalibrationObject(geometry.toArray(new LatLon[0]));
             }
+            if( id >= 0 )
+                result.setId(id);
+            result.setBasicInfo(position, author, description, date);
+            result.setDeprecated(abandonDate, abandonAuthor, abandonReason);
+            return result;
         }
     }
Index: /applications/editors/josm/plugins/imagery_offset_db/src/iodb/ImageryOffsetBase.java
===================================================================
--- /applications/editors/josm/plugins/imagery_offset_db/src/iodb/ImageryOffsetBase.java	(revision 29375)
+++ /applications/editors/josm/plugins/imagery_offset_db/src/iodb/ImageryOffsetBase.java	(revision 29376)
@@ -37,6 +37,8 @@
     }
 
-    public void setAbandonDate(Date abandonDate) {
+    public void setDeprecated(Date abandonDate, String author, String reason) {
         this.abandonDate = abandonDate;
+        this.abandonAuthor = author;
+        this.abandonReason = reason;
     }
 
Index: /applications/editors/josm/plugins/imagery_offset_db/src/iodb/ImageryOffsetTools.java
===================================================================
--- /applications/editors/josm/plugins/imagery_offset_db/src/iodb/ImageryOffsetTools.java	(revision 29375)
+++ /applications/editors/josm/plugins/imagery_offset_db/src/iodb/ImageryOffsetTools.java	(revision 29376)
@@ -1,4 +1,5 @@
 package iodb;
 
+import java.text.SimpleDateFormat;
 import java.util.*;
 import org.openstreetmap.josm.Main;
@@ -18,4 +19,5 @@
 public class ImageryOffsetTools {
     public static final String DIALOG_TITLE = tr("Imagery Offset");
+    public static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");
     
     public static ImageryLayer getTopImageryLayer() {
Index: /applications/editors/josm/plugins/imagery_offset_db/src/iodb/OffsetDialog.java
===================================================================
--- /applications/editors/josm/plugins/imagery_offset_db/src/iodb/OffsetDialog.java	(revision 29375)
+++ /applications/editors/josm/plugins/imagery_offset_db/src/iodb/OffsetDialog.java	(revision 29376)
@@ -1,9 +1,14 @@
 package iodb;
 
+import java.awt.FlowLayout;
 import java.awt.GridLayout;
+import java.awt.Insets;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
-import java.util.List;
+import java.awt.event.KeyEvent;
+import java.util.*;
 import javax.swing.*;
+import javax.swing.border.CompoundBorder;
+import javax.swing.border.EmptyBorder;
 import org.openstreetmap.josm.Main;
 import static org.openstreetmap.josm.tools.I18n.tr;
@@ -15,32 +20,91 @@
  */
 public class OffsetDialog extends JDialog implements ActionListener {
+    protected static final String PREF_CALIBRATION = "iodb.show.calibration";
+    protected static final String PREF_DEPRECATED = "iodb.show.deprecated";
+
     private List<ImageryOffsetBase> offsets;
     private ImageryOffsetBase selectedOffset;
+    private JPanel buttonPanel;
 
     public OffsetDialog( List<ImageryOffsetBase> offsets ) {
-        super(JOptionPane.getFrameForComponent(Main.parent), tr("Imagery Offset"), ModalityType.DOCUMENT_MODAL);
+        super(JOptionPane.getFrameForComponent(Main.parent), ImageryOffsetTools.DIALOG_TITLE, ModalityType.DOCUMENT_MODAL);
         setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
+        setResizable(false);
         this.offsets = offsets;
+
+        // make this dialog close on "escape"
+        getRootPane().registerKeyboardAction(this,
+                KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0),
+                JComponent.WHEN_IN_FOCUSED_WINDOW);
     }
     
     private void prepareDialog() {
-        JPanel buttonPanel = new JPanel(new GridLayout(offsets.size() + 1, 1));
-        for( ImageryOffsetBase offset : offsets ) {
+        Box dialog = new Box(BoxLayout.Y_AXIS);
+        updateButtonPanel();
+        // todo: calibration objects and deprecated offsets button
+        final JCheckBox calibrationBox = new JCheckBox(tr("Hide calibration geometries"));
+        calibrationBox.setSelected(Main.pref.getBoolean(PREF_CALIBRATION, true));
+        calibrationBox.addActionListener(new ActionListener() {
+            public void actionPerformed( ActionEvent e ) {
+                Main.pref.put(PREF_CALIBRATION, calibrationBox.isSelected());
+                updateButtonPanel();
+            }
+        });
+        final JCheckBox deprecatedBox = new JCheckBox(tr("Show deprecated offsets"));
+        deprecatedBox.setSelected(Main.pref.getBoolean(PREF_DEPRECATED, false));
+        deprecatedBox.addActionListener(new ActionListener() {
+            public void actionPerformed( ActionEvent e ) {
+                Main.pref.put(PREF_DEPRECATED, deprecatedBox.isSelected());
+                updateButtonPanel();
+            }
+        });
+        Box checkBoxPanel = new Box(BoxLayout.X_AXIS);
+        checkBoxPanel.add(calibrationBox);
+        checkBoxPanel.add(deprecatedBox);
+        JButton cancelButton = new JButton("Cancel");
+        cancelButton.addActionListener(this);
+        cancelButton.setAlignmentX(CENTER_ALIGNMENT);
+
+        dialog.add(buttonPanel);
+        dialog.add(checkBoxPanel);
+        dialog.add(cancelButton);
+
+        dialog.setBorder(new CompoundBorder(dialog.getBorder(), new EmptyBorder(5, 5, 5, 5)));
+        setContentPane(dialog);
+        pack();
+        setLocationRelativeTo(Main.parent);
+    }
+
+    private void updateButtonPanel() {
+        List<ImageryOffsetBase> filteredOffsets = filterOffsets();
+        if( buttonPanel == null )
+            buttonPanel = new JPanel();
+        buttonPanel.removeAll();
+        buttonPanel.setLayout(new GridLayout(filteredOffsets.size(), 1, 0, 5));
+        for( ImageryOffsetBase offset : filteredOffsets ) {
             OffsetDialogButton button = new OffsetDialogButton(offset);
             button.addActionListener(this);
-/*            JPopupMenu popupMenu = new JPopupMenu();
+            JPopupMenu popupMenu = new JPopupMenu();
             popupMenu.add(new OffsetInfoAction(offset));
             if( !offset.isDeprecated() )
                 popupMenu.add(new DeprecateOffsetAction(offset));
-            button.add(popupMenu);*/
+            button.setComponentPopupMenu(popupMenu);
             buttonPanel.add(button);
         }
-        // todo: calibration objects and deprecated offsets button
-        JButton cancelButton = new JButton("Cancel");
-        cancelButton.addActionListener(this);
-        buttonPanel.add(cancelButton); // todo: proper button
-        setContentPane(buttonPanel);
         pack();
-        setLocationRelativeTo(Main.parent);
+    }
+
+    private List<ImageryOffsetBase> filterOffsets() {
+        boolean showCalibration = Main.pref.getBoolean(PREF_CALIBRATION, true);
+        boolean showDeprecated = Main.pref.getBoolean(PREF_DEPRECATED, false);
+        List<ImageryOffsetBase> filteredOffsets = new ArrayList<ImageryOffsetBase>();
+        for( ImageryOffsetBase offset : offsets ) {
+            if( offset.isDeprecated() && !showDeprecated )
+                continue;
+            if( offset instanceof CalibrationObject && !showCalibration )
+                continue;
+            filteredOffsets.add(offset);
+        }
+        return filteredOffsets;
     }
     
Index: /applications/editors/josm/plugins/imagery_offset_db/src/iodb/StoreImageryOffsetAction.java
===================================================================
--- /applications/editors/josm/plugins/imagery_offset_db/src/iodb/StoreImageryOffsetAction.java	(revision 29375)
+++ /applications/editors/josm/plugins/imagery_offset_db/src/iodb/StoreImageryOffsetAction.java	(revision 29376)
@@ -46,31 +46,14 @@
         if( selectedObjects.size() == 1 ) {
             OsmPrimitive selection = selectedObjects.iterator().next();
-            if( selection instanceof Node || selection instanceof Way ) {
-                boolean suitable = !selection.isNewOrUndeleted() && !selection.isDeleted() && !selection.isModified();
-                if( selection instanceof Way ) {
-                    for( Node n : ((Way)selection).getNodes() )
-                        if( n.isNewOrUndeleted() || n.isDeleted() || n.isModified() )
-                            suitable = false;
-                } else if( selection.isReferredByWays(1) ) {
-                    suitable = false;
-                }
-                if( suitable ) {
-                    String[] options = new String[] {tr("Store calibration object"), tr("Store imagery offset"), tr("Cancel")};
-                    int result = JOptionPane.showOptionDialog(Main.parent,
-                            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,
-                            null, options, options[0]);
-                    if( result == 2 || result == JOptionPane.CLOSED_OPTION )
-                        return;
-                    if( result == 0 )
-                        calibration = selection;
-                } else {
-                    String[] options = new String[] {tr("Store imagery offset"), tr("Cancel")};
-                    int result = JOptionPane.showOptionDialog(Main.parent,
-                            tr("You have an object selected and might want to use it as a calibration object.\n"
-                             + "But in this case it should be uploaded to OSM server first."), ImageryOffsetTools.DIALOG_TITLE, JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE,
-                            null, options, options[1]);
-                    if( result == 1 || result == JOptionPane.CLOSED_OPTION )
-                        return;
-                }
+            if( (selection instanceof Node || selection instanceof Way) && !selection.isIncomplete() && !selection.isReferredByWays(1) ) {
+                String[] options = new String[] {tr("Store calibration geometry"), tr("Store imagery offset"), tr("Cancel")};
+                int result = JOptionPane.showOptionDialog(Main.parent,
+                        tr("The selected object can be used as a calibration geometry. What do you intend to do?"),
+                        ImageryOffsetTools.DIALOG_TITLE, JOptionPane.DEFAULT_OPTION, JOptionPane.QUESTION_MESSAGE,
+                        null, options, options[0]);
+                if( result == 2 || result == JOptionPane.CLOSED_OPTION )
+                    return;
+                if( result == 0 )
+                    calibration = selection;
             }
         }
@@ -88,13 +71,10 @@
             LatLon offset = ImageryOffsetTools.getLayerOffset(layer, center);
             offsetObj = new ImageryOffset(ImageryOffsetTools.getImageryID(layer), offset);
-            message = "You are registering an imagery offset.\n"
-                    + "Other users in this area will be able to use it for mapping.\n"
-                    + "Please make sure it is as precise as possible, and\n"
-                    + "describe a region this offset is applicable to.";
+            message = "You are registering an imagery offset. Other users in this area will be able to use it for mapping.\n"
+                    + "Please make sure it is as precise as possible, and describe a region this offset is applicable to.";
         } else {
             // register calibration object
             offsetObj = new CalibrationObject(calibration);
-            message = "You are registering calibration object.\n"
-                    + "It should be the most precisely positioned object,\n"
+            message = "You are registering a calibration geometry. It should be the most precisely positioned object,\n"
                     + "with clearly visible boundaries on various satellite imagery.\n"
                     + "Please describe a region where this object is located.";
