Changes in / [2024:2060] in josm


Ignore:
Location:
/trunk
Files:
49 added
11 deleted
91 edited

Legend:

Unmodified
Added
Removed
  • /trunk/presets/presets.xml

    r2024 r2060  
    24362436            <label text="Edit Hunting Stand" />
    24372437            <key key="amenity" value="hunting_stand" />
    2438             <check key="shelter" text="Shelter" default="off" delete_if_empty="true" />
    2439             <check key="hide" text="Hide" default="off" delete_if_empty="true" />
    2440             <check key="lock" text="Lock" default="off" delete_if_empty="true" />
    24412438            <combo key="height" text="Height" values="low,half,full,5,10,15,20" default="" delete_if_empty="true" />
     2439            <combo key="shelter" text="Shelter" values="yes,no,unknown" default="" delete_if_empty="true" />
     2440            <combo key="hide" text="Hide" values="yes,no,unknown" default="" delete_if_empty="true" />
     2441            <combo key="lock" text="Lock" values="yes,no,unknown" default="" delete_if_empty="true" />
    24422442        </item>
    24432443        <item name="Fountain" icon="presets/spring.png" type="node,closedway">
     
    26732673            <key key="amenity" value="bank" />
    26742674            <text key="name" text="Name" default="" delete_if_empty="true" />
     2675            <text key="operator" text="Operator" default="" delete_if_empty="true" />
    26752676            <combo key="opening_hours" text="Opening Hours" values="24/7,Mo-Fr 08:30-20:00,Tu-Su 08:00-15:00; Sa 08:00-12:00" default="" delete_if_empty="true" />
    26762677            <check key="atm" text="Automated Teller Machine" default="on" delete_if_empty="true" />
  • /trunk/src/org/openstreetmap/josm/Main.java

    r2024 r2060  
    22package org.openstreetmap.josm;
    33import static org.openstreetmap.josm.tools.I18n.tr;
     4import static org.openstreetmap.josm.tools.I18n.trn;
    45
    56import java.awt.BorderLayout;
     
    1011import java.awt.event.KeyEvent;
    1112import java.io.File;
     13import java.io.IOException;
    1214import java.net.URI;
    1315import java.net.URISyntaxException;
     16import java.util.ArrayList;
    1417import java.util.Collection;
     18import java.util.List;
    1519import java.util.Map;
    1620import java.util.StringTokenizer;
     
    2226import javax.swing.JComponent;
    2327import javax.swing.JFrame;
     28import javax.swing.JLabel;
    2429import javax.swing.JOptionPane;
    2530import javax.swing.JPanel;
    2631import javax.swing.UIManager;
    2732
     33import org.openstreetmap.josm.actions.OpenFileAction;
    2834import org.openstreetmap.josm.actions.SaveAction;
    2935import org.openstreetmap.josm.actions.downloadtasks.DownloadGpsTask;
     
    4551import org.openstreetmap.josm.gui.dialogs.LayerListDialog;
    4652import org.openstreetmap.josm.gui.download.DownloadDialog.DownloadTask;
     53import org.openstreetmap.josm.gui.io.SaveLayersDialog;
    4754import org.openstreetmap.josm.gui.layer.Layer;
    4855import org.openstreetmap.josm.gui.layer.OsmDataLayer;
     
    333340        //
    334341        try {
    335             CoordinateFormat format = CoordinateFormat.valueOf(Main.pref.get("coordinates"));
     342            //CoordinateFormat format = CoordinateFormat.valueOf(Main.pref.get("coordinates"));
    336343            CoordinateFormat.setCoordinateFormat(CoordinateFormat.valueOf(Main.pref.get("coordinates")));
    337344        } catch (IllegalArgumentException iae) {
     
    393400    }
    394401
    395     public static boolean breakBecauseUnsavedChanges() {
     402    public static boolean saveUnsavedModifications() {
     403        if (map == null) return true;
     404        SaveLayersDialog dialog = new SaveLayersDialog(Main.parent);
     405        List<OsmDataLayer> layersWithUnmodifiedChanges = new ArrayList<OsmDataLayer>();
     406        for (OsmDataLayer l: Main.map.mapView.getLayersOfType(OsmDataLayer.class)) {
     407            if (l.requiresSaveToFile() || l.requiresUploadToServer()) {
     408                layersWithUnmodifiedChanges.add(l);
     409            }
     410        }
     411        dialog.prepareForSavingAndUpdatingLayersBeforeExit();
     412        if (!layersWithUnmodifiedChanges.isEmpty()) {
     413            dialog.getModel().populate(layersWithUnmodifiedChanges);
     414            dialog.setVisible(true);
     415            switch(dialog.getUserAction()) {
     416                case CANCEL: return false;
     417                case PROCEED: return true;
     418                default: return false;
     419            }
     420        }
     421        return true;
     422    }
     423
     424    /**
     425     * Saves all {@see OsmDataLayer}s with an associated file and with unsaved
     426     * data modifications.
     427     *
     428     * @return true, if the save operation was successful; false, otherwise
     429     */
     430    public static boolean saveUnsavedModifications_old() {
    396431        Shortcut.savePrefs();
    397         if (map != null) {
    398             boolean modified = false;
    399             boolean uploadedModified = false;
    400             for (final Layer l : map.mapView.getAllLayers()) {
    401                 if (l instanceof OsmDataLayer && ((OsmDataLayer)l).isModified()) {
    402                     modified = true;
    403                     uploadedModified = ((OsmDataLayer)l).uploadedModified;
    404                     break;
    405                 }
    406             }
    407             if (modified) {
    408                 final String msg = uploadedModified ? "\n"
    409                         +tr("Hint: Some changes came from uploading new data to the server.") : "";
    410                         int result = new ExtendedDialog(parent, tr("Unsaved Changes"),
    411                                 new javax.swing.JLabel(tr("There are unsaved changes. Discard the changes and continue?")+msg),
    412                                 new String[] {tr("Save and Exit"), tr("Discard and Exit"), tr("Cancel")},
    413                                 new String[] {"save.png", "exit.png", "cancel.png"}).getValue();
    414 
    415                         // Save before exiting
    416                         if(result == 1) {
    417                             Boolean savefailed = false;
    418                             for (final Layer l : map.mapView.getAllLayers()) {
    419                                 if (l instanceof OsmDataLayer && ((OsmDataLayer)l).isModified()) {
    420                                     SaveAction save = new SaveAction();
    421                                     if(!save.doSave(l)) {
    422                                         savefailed = true;
    423                                     }
    424                                 }
    425                             }
    426                             return savefailed;
    427                         }
    428                         else if(result != 2) // Cancel exiting unless the 2nd button was clicked
    429                             return true;
    430             }
    431         }
    432         return false;
     432        if (map == null)
     433            return true; // nothing to save, return success
     434
     435        int numUnsavedLayers = 0;
     436        for (final OsmDataLayer l : map.mapView.getLayersOfType(OsmDataLayer.class)) {
     437            if (l.requiresSaveToFile()) {
     438                numUnsavedLayers++;
     439            }
     440        }
     441        if (numUnsavedLayers == 0)
     442            return true; // nothing to save, return success
     443
     444        String msg = trn(
     445                "There are unsaved changes in {0} layer. Discard the changes and continue?",
     446                "There are unsaved changes in {0} layers. Discard the changes and continue?",
     447                numUnsavedLayers,
     448                numUnsavedLayers
     449        );
     450
     451        ExtendedDialog ed = new ExtendedDialog(parent,
     452                tr("Unsaved Changes"),
     453                new String[] {tr("Save and Exit"), tr("Discard and Exit"), tr("Cancel")});
     454        ed.setButtonIcons(new String[] {"save.png", "exit.png", "cancel.png"});
     455        ed.setContent(new JLabel(msg));
     456        ed.showDialog();
     457
     458        switch(ed.getValue()) {
     459            case 2: /* discard and exit */ return true;
     460            case 3: /* cancel */ return false;
     461        }
     462        boolean savefailed = false;
     463        for (OsmDataLayer l : map.mapView.getLayersOfType(OsmDataLayer.class)) {
     464            if(!new SaveAction().doSave(l)) {
     465                savefailed = true;
     466            }
     467        }
     468        return !savefailed;
    433469    }
    434470
     
    452488
    453489        if (s.startsWith("file:")) {
     490            File f = null;
    454491            try {
    455                 main.menu.openFile.openFile(new File(new URI(s)));
     492                f = new File(new URI(s));
    456493            } catch (URISyntaxException e) {
    457494                JOptionPane.showMessageDialog(
     
    462499                );
    463500            }
     501            try {
     502                if (f!=null) {
     503                    OpenFileAction.openFile(f);
     504                }
     505            }catch(IOException e) {
     506                e.printStackTrace();
     507                JOptionPane.showMessageDialog(
     508                        Main.parent,
     509                        tr("<html>Could not read file ''{0}\''.<br> Error is: <br>{1}</html>", f.getName(), e.getMessage()),
     510                        tr("Error"),
     511                        JOptionPane.ERROR_MESSAGE
     512                );
     513            }
    464514            return;
    465515        }
     
    474524            }
    475525        }
    476 
    477         main.menu.openFile.openFile(new File(s));
     526        File f = new File(s);
     527        try {
     528            OpenFileAction.openFile(f);
     529        }catch(IOException e) {
     530            e.printStackTrace();
     531            JOptionPane.showMessageDialog(
     532                    Main.parent,
     533                    tr("<html>Could not read file ''{0}\''.<br> Error is: <br>{1}</html>", f.getName(), e.getMessage()),
     534                    tr("Error"),
     535                    JOptionPane.ERROR_MESSAGE
     536            );
     537        }
    478538    }
    479539
  • /trunk/src/org/openstreetmap/josm/actions/AbstractInfoAction.java

    r2024 r2060  
    55
    66import java.awt.event.ActionEvent;
     7import java.net.URL;
    78import java.util.ArrayList;
    89import java.util.Iterator;
     
    3132     * @return the base URL, i.e. http://api.openstreetmap.org/browse
    3233     */
    33     protected String getBaseURL() {
     34    static public String getBaseBrowseUrl() {
    3435        String baseUrl = Main.pref.get("osm-server.url", "http://api.openstreetmap.org/api");
    3536        Pattern pattern = Pattern.compile("/api/?$");
    3637        String ret =  pattern.matcher(baseUrl).replaceAll("/browse");
    3738        if (ret.equals(baseUrl)) {
    38             System.out.println(tr("WARNING: unexpected format of API base URL. Redirection to history page for OSM primitive will probably fail. API base URL is: ''{0}''",baseUrl));
     39            System.out.println(tr("WARNING: unexpected format of API base URL. Redirection to info or history page for OSM primitive will probably fail. API base URL is: ''{0}''",baseUrl));
    3940        }
    4041        if (ret.startsWith("http://api.openstreetmap.org/")) {
     
    4546    }
    4647
    47     protected void launchBrowser() {
     48    /**
     49     * replies the base URL for browsing information about a user
     50     *
     51     * @return the base URL, i.e. http://ww.openstreetmap.org/user
     52     */
     53    static public String getBaseUserUrl() {
     54        String baseUrl = Main.pref.get("osm-server.url", "http://api.openstreetmap.org/api");
     55        Pattern pattern = Pattern.compile("/api/?$");
     56        String ret =  pattern.matcher(baseUrl).replaceAll("/user");
     57        if (ret.equals(baseUrl)) {
     58            System.out.println(tr("WARNING: unexpected format of API base URL. Redirection to user page for OSM user will probably fail. API base URL is: ''{0}''",baseUrl));
     59        }
     60        if (ret.startsWith("http://api.openstreetmap.org/")) {
     61            ret = ret.substring("http://api.openstreetmap.org/".length());
     62            ret = "http://www.openstreetmap.org/" + ret;
     63        }
     64        return ret;
     65    }
     66
     67    protected void launchBrowser(URL url) {
     68        OpenBrowser.displayUrl(
     69                url.toString()
     70        );
     71    }
     72
     73    protected void launchBrowser(String url) {
     74        OpenBrowser.displayUrl(
     75                url
     76        );
     77    }
     78
     79    protected void launchInfoBrowsersForSelectedPrimitives() {
    4880        ArrayList<OsmPrimitive> primitivesToShow = new ArrayList<OsmPrimitive>(getCurrentDataSet().getSelected());
    4981
     
    5284        Iterator<OsmPrimitive> it = primitivesToShow.iterator();
    5385        while(it.hasNext()) {
    54             if (it.next().id == 0) {
     86            if (it.next().getId() == 0) {
    5587                it.remove();
    5688            }
     
    74106        }
    75107        for(int i = 0; i < max; i++) {
    76             OpenBrowser.displayUrl(
    77                     createInfoUrl(primitivesToShow.get(i))
    78             );
     108            launchBrowser(createInfoUrl(primitivesToShow.get(i)));
    79109        }
    80110    }
    81111
    82112    public void actionPerformed(ActionEvent e) {
    83         launchBrowser();
     113        launchInfoBrowsersForSelectedPrimitives();
    84114    }
    85115
    86     protected abstract String createInfoUrl(OsmPrimitive primitive);
     116    protected abstract String createInfoUrl(Object infoObject);
    87117
    88118    @Override
  • /trunk/src/org/openstreetmap/josm/actions/AbstractMergeAction.java

    r2024 r2060  
    6666        layerList.setModel(new DefaultComboBoxModel(targetLayers.toArray()));
    6767        layerList.setSelectedIndex(0);
    68    
     68
    6969        JPanel pnl = new JPanel();
    7070        pnl.setLayout(new GridBagLayout());
    7171        pnl.add(new JLabel(tr("Please select the target layer.")), GBC.eol());
    7272        pnl.add(layerList, GBC.eol());
    73    
    74         int decision = new ExtendedDialog(Main.parent, tr("Select target layer"), pnl, new String[] { tr("Merge"),
    75             tr("Cancel") }, new String[] { "dialogs/mergedown", "cancel" }).getValue();
    76         if (decision != 1)
     73
     74        ExtendedDialog ed = new ExtendedDialog(Main.parent,
     75                tr("Select target layer"),
     76                new String[] { tr("Merge"), tr("Cancel") });
     77        ed.setButtonIcons(new String[] { "dialogs/mergedown", "cancel" });
     78        ed.setContent(pnl);
     79        ed.showDialog();
     80        if (ed.getValue() != 1)
    7781            return null;
     82
    7883        Layer targetLayer = (Layer) layerList.getSelectedItem();
    7984        return targetLayer;
  • /trunk/src/org/openstreetmap/josm/actions/ApiPreconditionChecker.java

    r2024 r2060  
    1 // License: GPL. For details, see LICENSE file.
    21package org.openstreetmap.josm.actions;
    32
     
    1615import org.openstreetmap.josm.data.osm.Way;
    1716import org.openstreetmap.josm.gui.ExceptionDialogUtil;
     17import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
    1818import org.openstreetmap.josm.io.OsmApi;
    1919import org.openstreetmap.josm.io.OsmApiInitializationException;
     
    2525        OsmApi api = OsmApi.getOsmApi();
    2626        try {
    27             api.initialize();
     27            api.initialize(NullProgressMonitor.INSTANCE);
    2828            long maxNodes = 0;
    2929            if (api.getCapabilities().isDefined("waynodes", "maximum")) {
     
    7171            for (Entry<String,String> e : osmPrimitive.entrySet()) {
    7272                if(e.getValue().length() > 255) {
    73                     if (osmPrimitive.deleted) {
     73                    if (osmPrimitive.isDeleted()) {
    7474                        // if OsmPrimitive is going to be deleted we automatically shorten the
    7575                        // value
     
    7777                                tr("Warning: automatically truncating value of tag ''{0}'' on deleted primitive {1}",
    7878                                        e.getKey(),
    79                                         Long.toString(osmPrimitive.id)
     79                                        Long.toString(osmPrimitive.getId())
    8080                                )
    8181                        );
     
    8585                    JOptionPane.showMessageDialog(Main.parent,
    8686                            tr("Length of value for tag ''{0}'' on primitive {1} exceeds the max. allowed length {2}. Values length is {3}.",
    87                                     e.getKey(), Long.toString(osmPrimitive.id), 255, e.getValue().length()
     87                                    e.getKey(), Long.toString(osmPrimitive.getId()), 255, e.getValue().length()
    8888                            ),
    8989                            tr("Precondition Violation"),
     
    103103                        tr("{0} nodes in way {1} exceed the max. allowed number of nodes {2}",
    104104                                ((Way)osmPrimitive).getNodesCount(),
    105                                 Long.toString(osmPrimitive.id),
     105                                Long.toString(osmPrimitive.getId()),
    106106                                maxNodes
    107107                        ),
  • /trunk/src/org/openstreetmap/josm/actions/CombineWayAction.java

    r2024 r2060  
    9090        HashSet<Relation> relationsUsingWays = new HashSet<Relation>();
    9191        for (Relation r : getCurrentDataSet().relations) {
    92             if (r.deleted || r.incomplete) {
     92            if (r.isDeleted() || r.incomplete) {
    9393                continue;
    9494            }
     
    118118        for (HashSet<Way> waylinks : backlinks.values()) {
    119119            if (!waylinks.containsAll(selectedWays)) {
    120                 int option = new ExtendedDialog(Main.parent,
     120
     121                ExtendedDialog ed = new ExtendedDialog(Main.parent,
    121122                        tr("Combine ways with different memberships?"),
    122                         tr("The selected ways have differing relation memberships.  "
    123                                 + "Do you still want to combine them?"),
    124                                 new String[] {tr("Combine Anyway"), tr("Cancel")},
    125                                 new String[] {"combineway.png", "cancel.png"}).getValue();
    126                 if (option == 1) {
     123                        new String[] {tr("Combine Anyway"), tr("Cancel")});
     124                ed.setButtonIcons(new String[] {"combineway.png", "cancel.png"});
     125                ed.setContent(tr("The selected ways have differing relation memberships.  "
     126                        + "Do you still want to combine them?"));
     127                ed.showDialog();
     128
     129                if (ed.getValue() == 1) {
    127130                    break;
    128131                }
     
    150153            Object secondTry = actuallyCombineWays(selectedWays, true);
    151154            if (secondTry instanceof List<?>) {
    152                 int option = new ExtendedDialog(Main.parent,
     155                ExtendedDialog ed = new ExtendedDialog(Main.parent,
    153156                        tr("Change directions?"),
    154                         tr("The ways can not be combined in their current directions.  "
    155                                 + "Do you want to reverse some of them?"),
    156                                 new String[] {tr("Reverse and Combine"), tr("Cancel")},
    157                                 new String[] {"wayflip.png", "cancel.png"}).getValue();
    158                 if (option != 1) return;
     157                        new String[] {tr("Reverse and Combine"), tr("Cancel")});
     158                ed.setButtonIcons(new String[] {"wayflip.png", "cancel.png"});
     159                ed.setContent(tr("The ways can not be combined in their current directions.  "
     160                        + "Do you want to reverse some of them?"));
     161                ed.showDialog();
     162                if (ed.getValue() != 1) return;
     163
    159164                nodeList = (List<Node>) secondTry;
    160165            } else {
     
    177182        for (Way w : selectedWays) {
    178183            modifyWay = w;
    179             if (w.id != 0) {
     184            if (w.getId() != 0) {
    180185                break;
    181186            }
     
    205210
    206211        if (!components.isEmpty()) {
    207             int answer = new ExtendedDialog(Main.parent,
     212
     213            ExtendedDialog ed = new ExtendedDialog(Main.parent,
    208214                    tr("Enter values for all conflicts."),
    209                     p,
    210                     new String[] {tr("Solve Conflicts"), tr("Cancel")},
    211                     new String[] {"dialogs/conflict.png", "cancel.png"}).getValue();
    212             if (answer != 1) return;
     215                    new String[] {tr("Solve Conflicts"), tr("Cancel")});
     216            ed.setButtonIcons(new String[] {"dialogs/conflict.png", "cancel.png"});
     217            ed.setContent(p);
     218            ed.showDialog();
     219
     220            if (ed.getValue() != 1) return;
    213221
    214222            for (Entry<String, JComboBox> e : components.entrySet()) {
  • /trunk/src/org/openstreetmap/josm/actions/DiskAccessAction.java

    r2024 r2060  
    77
    88import javax.swing.JFileChooser;
    9 import javax.swing.filechooser.FileFilter;
    109
    1110import org.openstreetmap.josm.Main;
    1211import org.openstreetmap.josm.gui.ExtendedDialog;
    13 import org.openstreetmap.josm.io.FileImporter;
    1412import org.openstreetmap.josm.tools.Shortcut;
    1513
     
    3937        fc.setMultiSelectionEnabled(multiple);
    4038        fc.setAcceptAllFileFilterUsed(false);
    41         FileFilter defaultFilter = null;
    42         for (FileImporter imExporter: ExtensionFileFilter.importers) {
    43             fc.addChoosableFileFilter(imExporter.filter);
    44             if (extension != null && extension.endsWith(imExporter.filter.defaultExtension)) {
    45                 defaultFilter = imExporter.filter;
    46             }
    47         }
    48 
    49         if (defaultFilter == null) {
    50             defaultFilter = new ExtensionFileFilter.AllFormatsImporter().filter;
    51         }
    52         fc.setFileFilter(defaultFilter);
     39        System.out.println("opening fc for extension " + extension);
     40        ExtensionFileFilter.applyChoosableImportFileFilters(fc, extension);
    5341
    5442        int answer = open ? fc.showOpenDialog(Main.parent) : fc.showSaveDialog(Main.parent);
  • /trunk/src/org/openstreetmap/josm/actions/ExitAction.java

    r2024 r2060  
    2121    public ExitAction() {
    2222        super(tr("Exit"), "exit", tr("Exit the application."),
    23         Shortcut.registerShortcut("system:menuexit", tr("Exit"), KeyEvent.VK_Q, Shortcut.GROUP_MENU), true);
     23                Shortcut.registerShortcut("system:menuexit", tr("Exit"), KeyEvent.VK_Q, Shortcut.GROUP_MENU), true);
    2424    }
    2525
    2626    public void actionPerformed(ActionEvent e) {
    27         if (!Main.breakBecauseUnsavedChanges()) {
     27        if (Main.saveUnsavedModifications()) {
    2828            Main.saveGuiGeometry();
    2929            System.exit(0);
  • /trunk/src/org/openstreetmap/josm/actions/ExtensionFileFilter.java

    r2024 r2060  
    77import java.util.ArrayList;
    88import java.util.Arrays;
    9 
     9import java.util.Collections;
     10import java.util.Comparator;
     11import java.util.LinkedList;
     12import java.util.List;
     13
     14import javax.swing.JFileChooser;
    1015import javax.swing.filechooser.FileFilter;
    1116
     
    2631 * filters used in JOSM.
    2732 *
    28  * @author imi
    2933 */
    3034public class ExtensionFileFilter extends FileFilter {
    31     private final String extension;
    32     private final String description;
    33     public final String defaultExtension;
    3435
    3536    /**
     
    4142    public static ArrayList<FileExporter> exporters = new ArrayList<FileExporter>(Arrays.asList(new GpxExporter(),
    4243            new OsmExporter(), new OsmGzipExporter(), new OsmBzip2Exporter()));
    43    
     44
     45
     46    private final String extensions;
     47    private final String description;
     48    /**
     49     * @deprecated use {@see #getDefaultExtension()
     50     */
     51    @Deprecated
     52    public final String defaultExtension;
     53
     54
     55    static protected void sort(List<ExtensionFileFilter> filters) {
     56        Collections.sort(
     57                filters,
     58                new Comparator<ExtensionFileFilter>() {
     59                    private AllFormatsImporter all = new AllFormatsImporter();
     60                    public int compare(ExtensionFileFilter o1, ExtensionFileFilter o2) {
     61                        if (o1.getDescription().equals(all.filter.getDescription())) return 1;
     62                        if (o2.getDescription().equals(all.filter.getDescription())) return -1;
     63                        return o1.getDescription().compareTo(o2.getDescription());
     64                    }
     65                }
     66        );
     67    }
     68
     69    /**
     70     * Replies an ordered list of {@see ExtensionFileFilter}s for importing.
     71     * The list is ordered according to their description, an {@see AllFormatsImporter}
     72     * is append at the end.
     73     *
     74     * @return an ordered list of {@see ExtensionFileFilter}s for importing.
     75     */
     76    public static List<ExtensionFileFilter> getImportExtensionFileFilters() {
     77        LinkedList<ExtensionFileFilter> filters = new LinkedList<ExtensionFileFilter>();
     78        for (FileImporter importer : importers) {
     79            if (filters.contains(importer.filter)) {
     80                continue;
     81            }
     82            filters.add(importer.filter);
     83        }
     84        sort(filters);
     85        return filters;
     86    }
     87
     88    /**
     89     * Replies an ordered list of {@see ExtensionFileFilter}s for exporting.
     90     * The list is ordered according to their description, an {@see AllFormatsImporter}
     91     * is append at the end.
     92     *
     93     * @return an ordered list of {@see ExtensionFileFilter}s for exporting.
     94     */
     95    public static List<ExtensionFileFilter> getExportExtensionFileFilters() {
     96        LinkedList<ExtensionFileFilter> filters = new LinkedList<ExtensionFileFilter>();
     97        for (FileExporter exporter : exporters) {
     98            if (filters.contains(exporter.filter)) {
     99                continue;
     100            }
     101            filters.add(exporter.filter);
     102        }
     103        sort(filters);
     104        return filters;
     105    }
     106
     107    /**
     108     * Replies the default {@see ExtensionFileFilter} for a given extension
     109     *
     110     * @param extension the extension
     111     * @return the default {@see ExtensionFileFilter} for a given extension
     112     */
     113    public static ExtensionFileFilter getDefaultImportExtensionFileFilter(String extension) {
     114        if (extension == null) return new AllFormatsImporter().filter;
     115        for (FileImporter importer : importers) {
     116            if (extension.equals(importer.filter.getDefaultExtension()))
     117                return importer.filter;
     118        }
     119        return new AllFormatsImporter().filter;
     120    }
     121
     122    /**
     123     * Replies the default {@see ExtensionFileFilter} for a given extension
     124     *
     125     * @param extension the extension
     126     * @return the default {@see ExtensionFileFilter} for a given extension
     127     */
     128    public static ExtensionFileFilter getDefaultExportExtensionFileFilter(String extension) {
     129        if (extension == null) return new AllFormatsImporter().filter;
     130        for (FileExporter exporter : exporters) {
     131            if (extension.equals(exporter.filter.getDefaultExtension()))
     132                return exporter.filter;
     133        }
     134        return new AllFormatsImporter().filter;
     135    }
     136
     137    /**
     138     * Applies the choosable {@see FileFilter} to a {@see JFileChooser} before using the
     139     * file chooser for selecting a file for reading.
     140     *
     141     * @param fileChooser the file chooser
     142     * @param extension the default extension
     143     */
     144    public static void applyChoosableImportFileFilters(JFileChooser fileChooser, String extension) {
     145        for (ExtensionFileFilter filter: getImportExtensionFileFilters()) {
     146            fileChooser.addChoosableFileFilter(filter);
     147        }
     148        fileChooser.setFileFilter(getDefaultImportExtensionFileFilter(extension));
     149    }
     150
     151    /**
     152     * Applies the choosable {@see FileFilter} to a {@see JFileChooser} before using the
     153     * file chooser for selecting a file for writing.
     154     *
     155     * @param fileChooser the file chooser
     156     * @param extension the default extension
     157     */
     158    public static void applyChoosableExportFileFilters(JFileChooser fileChooser, String extension) {
     159        for (ExtensionFileFilter filter: getExportExtensionFileFilters()) {
     160            fileChooser.addChoosableFileFilter(filter);
     161        }
     162        fileChooser.setFileFilter(getDefaultExportExtensionFileFilter(extension));
     163    }
     164
    44165    /**
    45166     * Construct an extension file filter by giving the extension to check after.
    46167     */
    47     public ExtensionFileFilter(String extension, String defExt, String description) {
    48         this.extension = extension;
    49         defaultExtension = defExt;
     168    public ExtensionFileFilter(String extension, String defaultExtension, String description) {
     169        this.extensions = extension;
     170        this.defaultExtension = defaultExtension;
    50171        this.description = description;
    51172    }
     
    53174    public boolean acceptName(String filename) {
    54175        String name = filename.toLowerCase();
    55         for (String ext : extension.split(","))
     176        for (String ext : extensions.split(","))
    56177            if (name.endsWith("."+ext))
    57178                return true;
     
    68189        return description;
    69190    }
    70    
     191
     192    public String getDefaultExtension() {
     193        return defaultExtension;
     194    }
     195
    71196    /**
    72197     * Dummy importer that adds the "All Formats"-Filter when opening files
     
    75200        public AllFormatsImporter() {
    76201            super(
    77                 new ExtensionFileFilter("osm,xml,osm.gz,osm.bz2,osm.bz,gpx,gpx.gz,nmea,nme,nma,txt", "", tr("All Formats")
    78                         + " (*.gpx *.osm *.nmea ...)"));
     202                    new ExtensionFileFilter("osm,xml,osm.gz,osm.bz2,osm.bz,gpx,gpx.gz,nmea,nme,nma,txt,wms", "", tr("All Formats")
     203                            + " (*.gpx *.osm *.nmea ...)"));
    79204        }
    80205        @Override public boolean acceptFile(File pathname) {
     
    82207        }
    83208    }
     209
     210    @Override
     211    public int hashCode() {
     212        final int prime = 31;
     213        int result = 1;
     214        result = prime * result + ((defaultExtension == null) ? 0 : defaultExtension.hashCode());
     215        result = prime * result + ((description == null) ? 0 : description.hashCode());
     216        result = prime * result + ((extensions == null) ? 0 : extensions.hashCode());
     217        return result;
     218    }
     219
     220    @Override
     221    public boolean equals(Object obj) {
     222        if (this == obj)
     223            return true;
     224        if (obj == null)
     225            return false;
     226        if (getClass() != obj.getClass())
     227            return false;
     228        ExtensionFileFilter other = (ExtensionFileFilter) obj;
     229        if (defaultExtension == null) {
     230            if (other.defaultExtension != null)
     231                return false;
     232        } else if (!defaultExtension.equals(other.defaultExtension))
     233            return false;
     234        if (description == null) {
     235            if (other.description != null)
     236                return false;
     237        } else if (!description.equals(other.description))
     238            return false;
     239        if (extensions == null) {
     240            if (other.extensions != null)
     241                return false;
     242        } else if (!extensions.equals(other.extensions))
     243            return false;
     244        return true;
     245    }
    84246}
  • /trunk/src/org/openstreetmap/josm/actions/HistoryInfoAction.java

    r2024 r2060  
    2020
    2121    @Override
    22     protected  String createInfoUrl(OsmPrimitive primitive) {
    23         return getBaseURL() + "/" + OsmPrimitiveType.from(primitive).getAPIName() + "/" + primitive.id + "/history";
     22    protected  String createInfoUrl(Object infoObject) {
     23        OsmPrimitive primitive = (OsmPrimitive)infoObject;
     24        return getBaseBrowseUrl() + "/" + OsmPrimitiveType.from(primitive).getAPIName() + "/" + primitive.getId() + "/history";
    2425    }
    2526}
  • /trunk/src/org/openstreetmap/josm/actions/InfoAction.java

    r2024 r2060  
    2020
    2121    @Override
    22     protected  String createInfoUrl(OsmPrimitive primitive) {
    23         return getBaseURL() + "/" + OsmPrimitiveType.from(primitive).getAPIName() + "/" + primitive.id;
     22    protected  String createInfoUrl(Object infoObject) {
     23        OsmPrimitive primitive = (OsmPrimitive)infoObject;
     24        return getBaseBrowseUrl() + "/" + OsmPrimitiveType.from(primitive).getAPIName() + "/" + primitive.getId();
    2425    }
    2526}
  • /trunk/src/org/openstreetmap/josm/actions/MergeNodesAction.java

    r2024 r2060  
    9595        Node useNode = null;
    9696        for (Node n: selectedNodes) {
    97             if (n.id > 0) {
     97            if (n.getId() > 0) {
    9898                useNode = n;
    9999                break;
     
    127127        HashSet<Relation> relationsUsingNodes = new HashSet<Relation>();
    128128        for (Relation r : getCurrentDataSet().relations) {
    129             if (r.deleted || r.incomplete) {
     129            if (r.isDeleted() || r.incomplete) {
    130130                continue;
    131131            }
     
    155155        for (HashSet<Node> nodelinks : backlinks.values()) {
    156156            if (!nodelinks.containsAll(allNodes)) {
    157                 int option = new ExtendedDialog(Main.parent,
     157                ExtendedDialog ed = new ExtendedDialog(Main.parent,
    158158                        tr("Merge nodes with different memberships?"),
    159                         tr("The selected nodes have differing relation memberships.  "
    160                                 + "Do you still want to merge them?"),
    161                                 new String[] {tr("Merge Anyway"), tr("Cancel")},
    162                                 new String[] {"mergenodes.png", "cancel.png"}).getValue();
    163                 if (option == 1) {
     159                        new String[] {tr("Merge Anyway"), tr("Cancel")});
     160                ed.setButtonIcons(new String[] {"mergenodes.png", "cancel.png"});
     161                ed.setContent(tr("The selected nodes have differing relation memberships.  "
     162                        + "Do you still want to merge them?"));
     163                ed.showDialog();
     164
     165                if (ed.getValue() == 1) {
    164166                    break;
    165167                }
     
    217219
    218220        for (Way w : getCurrentDataSet().ways) {
    219             if (w.deleted || w.incomplete || w.getNodesCount() < 1) {
     221            if (w.isDeleted() || w.incomplete || w.getNodesCount() < 1) {
    220222                continue;
    221223            }
  • /trunk/src/org/openstreetmap/josm/actions/OpenFileAction.java

    r2024 r2060  
    88import java.io.File;
    99import java.io.IOException;
     10import java.util.Arrays;
     11import java.util.List;
    1012
    1113import javax.swing.JFileChooser;
     
    1315
    1416import org.openstreetmap.josm.Main;
     17import org.openstreetmap.josm.gui.PleaseWaitRunnable;
    1518import org.openstreetmap.josm.io.FileImporter;
     19import org.openstreetmap.josm.io.OsmTransferException;
    1620import org.openstreetmap.josm.tools.Shortcut;
     21import org.xml.sax.SAXException;
    1722
    1823/**
     
    3742            return;
    3843        File[] files = fc.getSelectedFiles();
    39         for (int i = files.length; i > 0; --i) {
    40             openFile(files[i-1]);
    41         }
    42     }
    43 
    44     /**
    45      * Open the given file.
    46      */
    47     public void openFile(File file) {
    48         try {
    49             System.out.println("Open file: " + file.getAbsolutePath() + " (" + file.length() + " bytes)");
    50             for (FileImporter importer : ExtensionFileFilter.importers)
    51                 if (importer.acceptFile(file)) {
    52                     importer.importData(file);
    53                 }
    54         } catch (IOException x) {
    55             x.printStackTrace();
    56             JOptionPane.showMessageDialog(
    57                     Main.parent,
    58                     tr("<html>Could not read file ''{0}\''. Error is: <br>{1}</html>", file.getName(), x.getMessage()),
    59                     tr("Error"),
    60                     JOptionPane.ERROR_MESSAGE
    61             );
    62 
    63         }
     44        OpenFileTask task = new OpenFileTask(Arrays.asList(files));
     45        Main.worker.submit(task);
    6446    }
    6547
     
    6850        setEnabled(! Main.applet);
    6951    }
     52
     53    static public void openFile(File f) throws IOException {
     54        for (FileImporter importer : ExtensionFileFilter.importers)
     55            if (importer.acceptFile(f)) {
     56                importer.importData(f);
     57            }
     58    }
     59
     60    static public class OpenFileTask extends PleaseWaitRunnable {
     61        private List<File> files;
     62        private boolean cancelled;
     63
     64        public OpenFileTask(List<File> files) {
     65            super(tr("Opening files"), false /* don't ignore exception */);
     66            this.files = files;
     67        }
     68        @Override
     69        protected void cancel() {
     70            this.cancelled = true;
     71        }
     72
     73        @Override
     74        protected void finish() {
     75            // do nothing
     76        }
     77
     78        @Override
     79        protected void realRun() throws SAXException, IOException, OsmTransferException {
     80            if (files == null || files.isEmpty()) return;
     81            getProgressMonitor().setTicks(files.size());
     82            for (File f : files) {
     83                if (cancelled) return;
     84                getProgressMonitor().subTask(tr("Opening file ''{0}'' ...", f.getAbsolutePath()));
     85                try {
     86                    System.out.println("Open file: " + f.getAbsolutePath() + " (" + f.length() + " bytes)");
     87                    openFile(f);
     88                } catch (Exception e) {
     89                    e.printStackTrace();
     90                    JOptionPane.showMessageDialog(
     91                            Main.parent,
     92                            tr("<html>Could not read file ''{0}\''.<br> Error is: <br>{1}</html>", f.getName(), e.getMessage()),
     93                            tr("Error"),
     94                            JOptionPane.ERROR_MESSAGE
     95                    );
     96                }
     97                getProgressMonitor().worked(1);
     98            }
     99        }
     100    }
    70101}
  • /trunk/src/org/openstreetmap/josm/actions/PasteTagsAction.java

    r2024 r2060  
    126126    protected Map<OsmPrimitiveType, Integer> getSourceStatistics() {
    127127        HashMap<OsmPrimitiveType, Integer> ret = new HashMap<OsmPrimitiveType, Integer>();
    128         for (Class type: new Class[] {Node.class, Way.class, Relation.class}) {
     128        for (Class<? extends OsmPrimitive> type: new Class[] {Node.class, Way.class, Relation.class}) {
    129129            if (!getSourceTagsByType(type).isEmpty()) {
    130130                ret.put(OsmPrimitiveType.from(type), getSourcePrimitivesByType(type).size());
     
    136136    protected Map<OsmPrimitiveType, Integer> getTargetStatistics() {
    137137        HashMap<OsmPrimitiveType, Integer> ret = new HashMap<OsmPrimitiveType, Integer>();
    138         for (Class type: new Class[] {Node.class, Way.class, Relation.class}) {
     138        for (Class<? extends OsmPrimitive> type: new Class[] {Node.class, Way.class, Relation.class}) {
    139139            int count = getSubcollectionByType(getEditLayer().data.getSelected(), type).size();
    140140            if (count > 0) {
     
    156156    protected void pasteFromHomogeneousSource(Collection<? extends OsmPrimitive> targets) {
    157157        TagCollection tc = null;
    158         Class sourceType = null;
    159         for (Class type : new Class[] {Node.class, Way.class, Relation.class}) {
     158        for (Class<? extends OsmPrimitive> type : new Class[] {Node.class, Way.class, Relation.class}) {
    160159            TagCollection tc1 = getSourceTagsByType(type);
    161160            if (!tc1.isEmpty()) {
    162161                tc = tc1;
    163                 sourceType = type;
    164162            }
    165163        }
  • /trunk/src/org/openstreetmap/josm/actions/SaveActionBase.java

    r2024 r2060  
    7272            layer.setName(file.getName());
    7373            layer.setAssociatedFile(file);
     74            if (layer instanceof OsmDataLayer) {
     75                ((OsmDataLayer) layer).onPostSaveToFile();
     76            }
    7477            Main.parent.repaint();
    7578        } catch (IOException e) {
     
    8891     */
    8992    public boolean checkSaveConditions(Layer layer) {
    90         if (layer == null) {
    91             JOptionPane.showMessageDialog(
    92                     Main.parent,
    93                     tr("Internal Error: cannot check conditions for no layer. Please report this as a bug."),
    94                     tr("Error"),
    95                     JOptionPane.ERROR_MESSAGE
    96             );
    97             return false;
    98         }
    99         if (Main.map == null) {
    100             JOptionPane.showMessageDialog(
    101                     Main.parent,
    102                     tr("No document open so nothing to save."),
    103                     tr("Warning"),
    104                     JOptionPane.WARNING_MESSAGE
    105             );
    106             return false;
    107         }
    108 
    10993        if (layer instanceof OsmDataLayer && isDataSetEmpty((OsmDataLayer)layer) && 1 != new ExtendedDialog(Main.parent, tr("Empty document"), tr("The document contains no data."), new String[] {tr("Save anyway"), tr("Cancel")}, new String[] {"save.png", "cancel.png"}).getValue())
    11094            return false;
     
    128112    public static File openFileDialog(Layer layer) {
    129113        if (layer instanceof OsmDataLayer)
    130             return createAndOpenSaveFileChooser(tr("Save OSM file"), ".osm");
     114            return createAndOpenSaveFileChooser(tr("Save OSM file"), "osm");
    131115        else if (layer instanceof GpxLayer)
    132             return createAndOpenSaveFileChooser(tr("Save GPX file"), ".gpx");
    133         return createAndOpenSaveFileChooser(tr("Save Layer"), ".lay");
     116            return createAndOpenSaveFileChooser(tr("Save GPX file"), "gpx");
     117        return createAndOpenSaveFileChooser(tr("Save Layer"), "lay");
    134118    }
    135119
     
    144128    private boolean isDataSetEmpty(OsmDataLayer layer) {
    145129        for (OsmPrimitive osm : layer.data.allNonDeletedPrimitives())
    146             if (!osm.deleted || osm.id > 0)
     130            if (!osm.isDeleted() || osm.getId() > 0)
    147131                return false;
    148132        return true;
     
    183167        fc.setMultiSelectionEnabled(false);
    184168        fc.setAcceptAllFileFilterUsed(false);
    185 
    186         FileFilter defaultFilter = null;
    187         for (FileExporter exporter : ExtensionFileFilter.exporters) {
    188             fc.addChoosableFileFilter(exporter.filter);
    189             if (extension.endsWith(exporter.filter.defaultExtension)) {
    190                 defaultFilter = exporter.filter;
    191             }
    192         }
    193         if (defaultFilter != null) {
    194             fc.setFileFilter(defaultFilter);
    195         }
    196 
     169        ExtensionFileFilter.applyChoosableExportFileFilters(fc, extension);
    197170        int answer = fc.showSaveDialog(Main.parent);
    198171        if (answer != JFileChooser.APPROVE_OPTION)
     
    210183                FileFilter ff = fc.getFileFilter();
    211184                if (ff instanceof ExtensionFileFilter) {
    212                     fn += "." + ((ExtensionFileFilter)ff).defaultExtension;
     185                    fn += "." + ((ExtensionFileFilter)ff).getDefaultExtension();
    213186                } else {
    214187                    fn += extension;
  • /trunk/src/org/openstreetmap/josm/actions/ShowStatusReportAction.java

    r2024 r2060  
    7373                while ((line = input.readLine()) != null) {
    7474                    // Skip potential private information
    75                     if (line.trim().toLowerCase().startsWith("osm-server.username"))
     75                    if (line.trim().toLowerCase().startsWith("osm-server.username")) {
    7676                        continue;
    77                     if (line.trim().toLowerCase().startsWith("osm-server.password"))
     77                    }
     78                    if (line.trim().toLowerCase().startsWith("osm-server.password")) {
    7879                        continue;
    79                     if (line.trim().toLowerCase().startsWith("marker.show"))
     80                    }
     81                    if (line.trim().toLowerCase().startsWith("marker.show")) {
    8082                        continue;
     83                    }
    8184
    8285                    text.append(line);
     
    97100        sp.setPreferredSize(new Dimension(600, 500));
    98101
    99         int result = new ExtendedDialog(Main.parent, tr(tr("Status Report")), sp,
    100                 new String[] {tr("Copy to clipboard and close"), tr("Close") },
    101                 new String[] {"copy.png", "cancel.png" }).getValue();
     102        ExtendedDialog ed = new ExtendedDialog(Main.parent,
     103                tr("Status Report"),
     104                new String[] {tr("Copy to clipboard and close"), tr("Close") });
     105        ed.setButtonIcons(new String[] {"copy.png", "cancel.png" });
     106        ed.setContent(sp);
     107        ed.showDialog();
    102108
    103         if(result != 1) return;
     109        if(ed.getValue() != 1) return;
    104110        try {
    105111            Toolkit.getDefaultToolkit().getSystemClipboard().setContents(
     
    107113                        public void lostOwnership(Clipboard clipboard, Transferable contents) {}
    108114                    }
    109              );
     115            );
    110116        }
    111117        catch (RuntimeException x) {}
  • /trunk/src/org/openstreetmap/josm/actions/SplitWayAction.java

    r2024 r2060  
    102102            for (Node n : selectedNodes) {
    103103                for (Way w : getCurrentDataSet().ways) {
    104                     if (w.deleted || w.incomplete) {
     104                    if (w.isDeleted() || w.incomplete) {
    105105                        continue;
    106106                    }
     
    293293
    294294        for (Relation r : getCurrentDataSet().relations) {
    295             if (r.deleted || r.incomplete) {
     295            if (r.isDeleted() || r.incomplete) {
    296296                continue;
    297297            }
  • /trunk/src/org/openstreetmap/josm/actions/UnGlueAction.java

    r2024 r2060  
    6666            int count = 0;
    6767            for (Way w : getCurrentDataSet().ways) {
    68                 if (w.deleted || w.incomplete || w.getNodesCount() < 1) {
     68                if (w.isDeleted() || w.incomplete || w.getNodesCount() < 1) {
    6969                    continue;
    7070                }
     
    9191                int count = 0;
    9292                for (Way w : getCurrentDataSet().ways) {
    93                     if (w.deleted || w.incomplete || w.getNodesCount() < 1) {
     93                    if (w.isDeleted() || w.incomplete || w.getNodesCount() < 1) {
    9494                        continue;
    9595                    }
     
    321321        HashSet<String> rolesToReAdd = null;
    322322        for (Relation r : getCurrentDataSet().relations) {
    323             if (r.deleted || r.incomplete) {
     323            if (r.isDeleted() || r.incomplete) {
    324324                continue;
    325325            }
     
    368368            // modify all ways containing the nodes
    369369            for (Way w : getCurrentDataSet().ways) {
    370                 if (w.deleted || w.incomplete || w.getNodesCount() < 1) {
     370                if (w.isDeleted() || w.incomplete || w.getNodesCount() < 1) {
    371371                    continue;
    372372                }
  • /trunk/src/org/openstreetmap/josm/actions/UpdateDataAction.java

    r2024 r2060  
    7979            // bounds defined? => use the bbox downloader
    8080            //
    81             new DownloadOsmTaskList().download(false, areas, new PleaseWaitProgressMonitor());
     81            new DownloadOsmTaskList().download(false, areas, new PleaseWaitProgressMonitor(tr("Updating data")));
    8282        }
    8383    }
  • /trunk/src/org/openstreetmap/josm/actions/UpdateSelectionAction.java

    r2024 r2060  
    166166        protected void initMultiFetchReaderWithNodes(MultiFetchServerObjectReader reader) {
    167167            for (OsmPrimitive primitive : toUpdate) {
    168                 if (primitive instanceof Node && primitive.id > 0) {
     168                if (primitive instanceof Node && primitive.getId() > 0) {
    169169                    reader.append((Node)primitive);
    170170                } else if (primitive instanceof Way) {
    171171                    Way way = (Way)primitive;
    172172                    for (Node node: way.getNodes()) {
    173                         if (node.id > 0) {
     173                        if (node.getId() > 0) {
    174174                            reader.append(node);
    175175                        }
     
    181181        protected void initMultiFetchReaderWithWays(MultiFetchServerObjectReader reader) {
    182182            for (OsmPrimitive primitive : toUpdate) {
    183                 if (primitive instanceof Way && primitive.id > 0) {
     183                if (primitive instanceof Way && primitive.getId() > 0) {
    184184                    reader.append((Way)primitive);
    185185                }
     
    189189        protected void initMultiFetchReaderWithRelations(MultiFetchServerObjectReader reader) {
    190190            for (OsmPrimitive primitive : toUpdate) {
    191                 if (primitive instanceof Relation && primitive.id > 0) {
     191                if (primitive instanceof Relation && primitive.getId() > 0) {
    192192                    reader.append((Relation)primitive);
    193193                }
  • /trunk/src/org/openstreetmap/josm/actions/UploadAction.java

    r2024 r2060  
    44import static org.openstreetmap.josm.tools.I18n.tr;
    55
    6 import java.awt.FlowLayout;
     6import java.awt.BorderLayout;
     7import java.awt.Dimension;
    78import java.awt.GridBagConstraints;
    89import java.awt.GridBagLayout;
    910import java.awt.event.ActionEvent;
     11import java.awt.event.ActionListener;
    1012import java.awt.event.KeyEvent;
    1113import java.io.IOException;
    1214import java.net.HttpURLConnection;
    1315import java.util.Collection;
     16import java.util.HashMap;
    1417import java.util.LinkedList;
    1518import java.util.List;
     19import java.util.Map;
    1620import java.util.logging.Logger;
    1721import java.util.regex.Matcher;
    1822import java.util.regex.Pattern;
    1923
     24import javax.swing.BoxLayout;
     25import javax.swing.ButtonGroup;
    2026import javax.swing.JCheckBox;
    2127import javax.swing.JLabel;
     
    2329import javax.swing.JOptionPane;
    2430import javax.swing.JPanel;
     31import javax.swing.JRadioButton;
    2532import javax.swing.JScrollPane;
     33import javax.swing.JTabbedPane;
    2634
    2735import org.openstreetmap.josm.Main;
     36import org.openstreetmap.josm.data.APIDataSet;
    2837import org.openstreetmap.josm.data.conflict.ConflictCollection;
     38import org.openstreetmap.josm.data.osm.Changeset;
    2939import org.openstreetmap.josm.data.osm.DataSet;
    3040import org.openstreetmap.josm.data.osm.OsmPrimitive;
     
    3444import org.openstreetmap.josm.gui.PleaseWaitRunnable;
    3545import org.openstreetmap.josm.gui.historycombobox.SuggestingJHistoryComboBox;
     46import org.openstreetmap.josm.gui.layer.OsmDataLayer;
    3647import org.openstreetmap.josm.gui.progress.ProgressMonitor;
     48import org.openstreetmap.josm.gui.tagging.TagEditorPanel;
     49import org.openstreetmap.josm.io.ChangesetProcessingType;
    3750import org.openstreetmap.josm.io.OsmApi;
    3851import org.openstreetmap.josm.io.OsmApiException;
    3952import org.openstreetmap.josm.io.OsmApiInitializationException;
     53import org.openstreetmap.josm.io.OsmChangesetCloseException;
    4054import org.openstreetmap.josm.io.OsmServerWriter;
    4155import org.openstreetmap.josm.tools.GBC;
    4256import org.openstreetmap.josm.tools.Shortcut;
     57import org.openstreetmap.josm.tools.WindowGeometry;
    4358import org.xml.sax.SAXException;
    4459
     
    108123    }
    109124
     125    public boolean checkPreUploadConditions(OsmDataLayer layer) {
     126        return checkPreUploadConditions(layer, new APIDataSet(layer.data));
     127    }
     128
     129    public boolean checkPreUploadConditions(OsmDataLayer layer, APIDataSet apiData) {
     130        ConflictCollection conflicts = layer.getConflicts();
     131        if (conflicts !=null && !conflicts.isEmpty()) {
     132            JOptionPane.showMessageDialog(
     133                    Main.parent,
     134                    tr("<html>There are unresolved conflicts in layer ''{0}''.<br>"
     135                            + "You have to resolve them first.<html>", layer.getName()),
     136                            tr("Warning"),
     137                            JOptionPane.WARNING_MESSAGE
     138            );
     139            return false;
     140        }
     141        // Call all upload hooks in sequence. The upload confirmation dialog
     142        // is one of these.
     143        for(UploadHook hook : uploadHooks)
     144            if(!hook.checkUpload(apiData.getPrimitivesToAdd(), apiData.getPrimitivesToUpdate(), apiData.getPrimitivesToDelete()))
     145                return false;
     146
     147        return true;
     148    }
     149
    110150    public void actionPerformed(ActionEvent e) {
    111151        if (!isEnabled())
     
    121161        }
    122162
    123         ConflictCollection conflicts = Main.map.mapView.getEditLayer().getConflicts();
    124         if (conflicts !=null && !conflicts.isEmpty()) {
    125             JOptionPane.showMessageDialog(
    126                     Main.parent,
    127                     tr("There are unresolved conflicts. You have to resolve these first."),
    128                     tr("Warning"),
    129                     JOptionPane.WARNING_MESSAGE
    130             );
    131             Main.map.conflictDialog.showDialog();
    132             return;
    133         }
    134 
    135         final LinkedList<OsmPrimitive> add = new LinkedList<OsmPrimitive>();
    136         final LinkedList<OsmPrimitive> update = new LinkedList<OsmPrimitive>();
    137         final LinkedList<OsmPrimitive> delete = new LinkedList<OsmPrimitive>();
    138         for (OsmPrimitive osm : getCurrentDataSet().allPrimitives()) {
    139             if (osm.get("josm/ignore") != null) {
    140                 continue;
    141             }
    142             if (osm.id == 0 && !osm.deleted) {
    143                 add.addLast(osm);
    144             } else if (osm.modified && !osm.deleted) {
    145                 update.addLast(osm);
    146             } else if (osm.deleted && osm.id != 0) {
    147                 delete.addFirst(osm);
    148             }
    149         }
    150 
    151         if (add.isEmpty() && update.isEmpty() && delete.isEmpty()) {
     163        APIDataSet apiData = new APIDataSet(Main.main.getCurrentDataSet());
     164        if (apiData.isEmpty()) {
    152165            JOptionPane.showMessageDialog(
    153166                    Main.parent,
    154167                    tr("No changes to upload."),
    155168                    tr("Warning"),
    156                     JOptionPane.WARNING_MESSAGE
     169                    JOptionPane.INFORMATION_MESSAGE
    157170            );
    158171            return;
    159172        }
    160 
    161         // Call all upload hooks in sequence. The upload confirmation dialog
    162         // is one of these.
    163         for(UploadHook hook : uploadHooks)
    164             if(!hook.checkUpload(add, update, delete))
    165                 return;
    166 
    167         final Collection<OsmPrimitive> all = new LinkedList<OsmPrimitive>();
    168         all.addAll(add);
    169         all.addAll(update);
    170         all.addAll(delete);
    171 
    172         Main.worker.execute(new UploadDiffTask(all));
     173        if (!checkPreUploadConditions(Main.map.mapView.getEditLayer(), apiData))
     174            return;
     175        Main.worker.execute(
     176                createUploadTask(
     177                        Main.map.mapView.getEditLayer(),
     178                        apiData.getPrimitives(),
     179                        UploadConfirmationHook.getUploadDialogPanel().getChangeset(),
     180                        UploadConfirmationHook.getUploadDialogPanel().getChangesetProcessingType()
     181                )
     182        );
    173183    }
    174184
     
    235245        );
    236246        switch(ret) {
    237         case JOptionPane.CLOSED_OPTION: return;
    238         case JOptionPane.CANCEL_OPTION: return;
    239         case 0: synchronizePrimitive(id); break;
    240         case 1: synchronizeDataSet(); break;
    241         default:
    242             // should not happen
    243             throw new IllegalStateException(tr("unexpected return value. Got {0}", ret));
     247            case JOptionPane.CLOSED_OPTION: return;
     248            case JOptionPane.CANCEL_OPTION: return;
     249            case 0: synchronizePrimitive(id); break;
     250            case 1: synchronizeDataSet(); break;
     251            default:
     252                // should not happen
     253                throw new IllegalStateException(tr("unexpected return value. Got {0}", ret));
    244254        }
    245255    }
     
    275285        );
    276286        switch(ret) {
    277         case JOptionPane.CLOSED_OPTION: return;
    278         case 1: return;
    279         case 0: synchronizeDataSet(); break;
    280         default:
    281             // should not happen
    282             throw new IllegalStateException(tr("unexpected return value. Got {0}", ret));
     287            case JOptionPane.CLOSED_OPTION: return;
     288            case 1: return;
     289            case 0: synchronizeDataSet(); break;
     290            default:
     291                // should not happen
     292                throw new IllegalStateException(tr("unexpected return value. Got {0}", ret));
    283293        }
    284294    }
     
    353363        }
    354364
     365        if (e instanceof OsmChangesetCloseException) {
     366            ExceptionDialogUtil.explainOsmChangesetCloseException((OsmChangesetCloseException)e);
     367            return;
     368        }
    355369        if (e instanceof OsmApiException) {
    356370            OsmApiException ex = (OsmApiException)e;
     
    441455
    442456
    443     class UploadConfirmationHook implements UploadHook {
    444 
    445         private JCheckBox cbUseAtomicUpload;
    446 
    447         protected JPanel buildChangesetControlPanel() {
    448             JPanel pnl = new JPanel();
    449             pnl.setLayout(new FlowLayout(FlowLayout.LEFT));
    450             pnl.add(cbUseAtomicUpload = new JCheckBox(tr("upload all changes in one request")));
    451             cbUseAtomicUpload.setToolTipText(tr("Enable to upload all changes in one request, disable to use one request per changed primitive"));
    452             boolean useAtomicUpload = Main.pref.getBoolean("osm-server.atomic-upload", true);
    453             cbUseAtomicUpload.setSelected(useAtomicUpload);
    454             cbUseAtomicUpload.setEnabled(OsmApi.getOsmApi().hasChangesetSupport());
    455             return pnl;
     457    static public class UploadConfirmationHook implements UploadHook {
     458        static private UploadDialogPanel uploadDialogPanel;
     459
     460        static public UploadDialogPanel getUploadDialogPanel() {
     461            if (uploadDialogPanel == null) {
     462                uploadDialogPanel = new UploadDialogPanel();
     463            }
     464            return uploadDialogPanel;
    456465        }
    457466
    458467        public boolean checkUpload(Collection<OsmPrimitive> add, Collection<OsmPrimitive> update, Collection<OsmPrimitive> delete) {
    459 
    460             JPanel p = new JPanel(new GridBagLayout());
    461 
    462             OsmPrimitivRenderer renderer = new OsmPrimitivRenderer();
    463 
    464             if (!add.isEmpty()) {
    465                 p.add(new JLabel(tr("Objects to add:")), GBC.eol());
    466                 JList l = new JList(add.toArray());
    467                 l.setCellRenderer(renderer);
    468                 l.setVisibleRowCount(l.getModel().getSize() < 6 ? l.getModel().getSize() : 10);
    469                 p.add(new JScrollPane(l), GBC.eol().fill());
    470             }
    471 
    472             if (!update.isEmpty()) {
    473                 p.add(new JLabel(tr("Objects to modify:")), GBC.eol());
    474                 JList l = new JList(update.toArray());
    475                 l.setCellRenderer(renderer);
    476                 l.setVisibleRowCount(l.getModel().getSize() < 6 ? l.getModel().getSize() : 10);
    477                 p.add(new JScrollPane(l), GBC.eol().fill());
    478             }
    479 
    480             if (!delete.isEmpty()) {
    481                 p.add(new JLabel(tr("Objects to delete:")), GBC.eol());
    482                 JList l = new JList(delete.toArray());
    483                 l.setCellRenderer(renderer);
    484                 l.setVisibleRowCount(l.getModel().getSize() < 6 ? l.getModel().getSize() : 10);
    485                 p.add(new JScrollPane(l), GBC.eol().fill());
    486             }
    487 
    488             p.add(new JLabel(tr("Provide a brief comment for the changes you are uploading:")), GBC.eol().insets(0, 5, 10, 3));
    489             SuggestingJHistoryComboBox cmt = new SuggestingJHistoryComboBox();
    490             List<String> cmtHistory = new LinkedList<String>(Main.pref.getCollection(HISTORY_KEY, new LinkedList<String>()));
    491             cmt.setHistory(cmtHistory);
    492             p.add(cmt, GBC.eol().fill(GBC.HORIZONTAL));
    493             //final JTextField cmt = new JTextField(lastCommitComment);
    494 
    495             // configuration options for atomic upload
    496             p.add(buildChangesetControlPanel(), GBC.eol().fill(GridBagConstraints.HORIZONTAL));
    497 
     468            final UploadDialogPanel panel = getUploadDialogPanel();
     469            panel.setUploadedPrimitives(add, update, delete);
     470
     471            ExtendedDialog dialog = new ExtendedDialog(
     472                    Main.parent,
     473                    tr("Upload these changes?"),
     474                    new String[] {tr("Upload Changes"), tr("Cancel")}
     475            ) {
     476                @Override
     477                public void setVisible(boolean visible) {
     478                    if (visible) {
     479                        new WindowGeometry(
     480                                panel.getClass().getName(),
     481                                WindowGeometry.centerInWindow(JOptionPane.getFrameForComponent(Main.parent), new Dimension(400,400))
     482                        ).apply(this);
     483                        panel.startUserInput();
     484                    } else {
     485                        new WindowGeometry(this).remember(panel.getClass().getName());
     486                    }
     487                    super.setVisible(visible);
     488                }
     489            };
     490
     491            dialog.setButtonIcons(new String[] {"upload.png", "cancel.png"});
     492            dialog.setContent(panel, false /* no scroll pane */);
    498493            while(true) {
    499                 int result = new ExtendedDialog(Main.parent,
    500                         tr("Upload these changes?"),
    501                         p,
    502                         new String[] {tr("Upload Changes"), tr("Cancel")},
    503                         new String[] {"upload.png", "cancel.png"}).getValue();
    504 
     494                dialog.showDialog();
     495                int result = dialog.getValue();
    505496                // cancel pressed
    506497                if (result != 1) return false;
    507 
    508498                // don't allow empty commit message
    509                 if (cmt.getText().trim().length() < 3) {
     499                if (! panel.hasChangesetComment()) {
    510500                    continue;
    511501                }
    512 
    513                 // store the history of comments
    514                 cmt.addCurrentItemToHistory();
    515                 Main.pref.putCollection(HISTORY_KEY, cmt.getHistory());
    516                 Main.pref.put("osm-server.atomic-upload", cbUseAtomicUpload.isSelected());
    517 
     502                panel.rememberUserInput();
    518503                break;
    519504            }
     
    522507    }
    523508
    524 
    525     class UploadDiffTask extends  PleaseWaitRunnable {
     509    public UploadDiffTask createUploadTask(OsmDataLayer layer, Collection<OsmPrimitive> toUpload, Changeset changeset, ChangesetProcessingType changesetProcessingType) {
     510        return new UploadDiffTask(layer, toUpload, changeset, changesetProcessingType);
     511    }
     512
     513    public class UploadDiffTask extends  PleaseWaitRunnable {
    526514        private boolean uploadCancelled = false;
    527515        private Exception lastException = null;
    528516        private Collection <OsmPrimitive> toUpload;
    529517        private OsmServerWriter writer;
    530 
    531         public UploadDiffTask(Collection <OsmPrimitive> toUpload) {
    532             super(tr("Uploading"),false /* don't ignore exceptions */);
     518        private OsmDataLayer layer;
     519        private Changeset changeset;
     520        private ChangesetProcessingType changesetProcessingType;
     521
     522        private UploadDiffTask(OsmDataLayer layer, Collection <OsmPrimitive> toUpload, Changeset changeset, ChangesetProcessingType changesetProcessingType) {
     523            super(tr("Uploading data for layer ''{0}''", layer.getName()),false /* don't ignore exceptions */);
    533524            this.toUpload = toUpload;
     525            this.layer = layer;
     526            this.changeset = changeset;
     527            this.changesetProcessingType = changesetProcessingType == null ? ChangesetProcessingType.USE_NEW_AND_CLOSE : changesetProcessingType;
    534528        }
    535529
     
    537531            writer = new OsmServerWriter();
    538532            try {
    539                 writer.uploadOsm(getCurrentDataSet().version, toUpload, progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false));
     533                ProgressMonitor monitor = progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false);
     534                writer.uploadOsm(layer.data.version, toUpload, changeset,changesetProcessingType, monitor);
    540535            } catch (Exception sxe) {
    541536                if (uploadCancelled) {
     
    554549            // partially uploaded
    555550            //
    556             getEditLayer().cleanupAfterUpload(writer.getProcessedPrimitives());
    557             DataSet.fireSelectionChanged(getEditLayer().data.getSelected());
    558             getEditLayer().fireDataChange();
     551            layer.cleanupAfterUpload(writer.getProcessedPrimitives());
     552            DataSet.fireSelectionChanged(layer.data.getSelected());
     553            layer.fireDataChange();
    559554            if (lastException != null) {
    560555                handleFailedUpload(lastException);
     556            } else {
     557                layer.onPostUploadToServer();
    561558            }
    562559        }
     
    565562            uploadCancelled = true;
    566563            if (writer != null) {
    567                 writer.disconnectActiveConnection();
     564                writer.cancel();
     565            }
     566        }
     567
     568        public boolean isSuccessful() {
     569            return !isCancelled() && !isFailed();
     570        }
     571
     572        public boolean isCancelled() {
     573            return uploadCancelled;
     574        }
     575
     576        public boolean isFailed() {
     577            return lastException != null;
     578        }
     579    }
     580
     581    /**
     582     * The panel displaying information about primitives to upload and providing
     583     * UI widgets for entering the changeset comment and other configuration
     584     * settings.
     585     *
     586     */
     587    static public class UploadDialogPanel extends JPanel {
     588
     589        private JList lstAdd;
     590        private JList lstUpdate;
     591        private JList lstDelete;
     592        private JLabel lblAdd;
     593        private JLabel lblUpdate;
     594        private JLabel lblDelete;
     595        private JPanel pnlLists;
     596        private JCheckBox cbUseAtomicUpload;
     597        private SuggestingJHistoryComboBox cmt;
     598        private TagEditorPanel tagEditorPanel;
     599        private JTabbedPane southTabbedPane;
     600        private ButtonGroup bgChangesetHandlingOptions;
     601        private Map<ChangesetProcessingType, JRadioButton> rbChangesetHandlingOptions;
     602
     603        protected JPanel buildListsPanel() {
     604            pnlLists = new JPanel();
     605            pnlLists.setLayout(new GridBagLayout());
     606
     607            return pnlLists;
     608        }
     609
     610        protected JPanel buildChangesetHandlingControlPanel() {
     611            JPanel pnl = new JPanel();
     612            pnl.setLayout(new BoxLayout(pnl, BoxLayout.Y_AXIS));
     613            bgChangesetHandlingOptions = new ButtonGroup();
     614            rbChangesetHandlingOptions = new HashMap<ChangesetProcessingType, JRadioButton>();
     615            ChangesetProcessingTypeChangedAction a = new ChangesetProcessingTypeChangedAction();
     616            for(ChangesetProcessingType type: ChangesetProcessingType.values()) {
     617                rbChangesetHandlingOptions.put(type, new JRadioButton());
     618                rbChangesetHandlingOptions.get(type).addActionListener(a);
     619            }
     620            JRadioButton rb = rbChangesetHandlingOptions.get(ChangesetProcessingType.USE_NEW_AND_CLOSE);
     621            rb.setText(tr("Use a new changeset and close it"));
     622            rb.setToolTipText(tr("Select to upload the data using a new changeset and to close the changeset after the upload"));
     623
     624            rb = rbChangesetHandlingOptions.get(ChangesetProcessingType.USE_NEW_AND_LEAVE_OPEN);
     625            rb.setText(tr("Use a new changeset and leave it open"));
     626            rb.setToolTipText(tr("Select to upload the data using a new changeset and to leave the changeset open after the upload"));
     627
     628            pnl.add(new JLabel(tr("Upload to a new or to an existing changeset?")));
     629            pnl.add(rbChangesetHandlingOptions.get(ChangesetProcessingType.USE_NEW_AND_CLOSE));
     630            pnl.add(rbChangesetHandlingOptions.get(ChangesetProcessingType.USE_NEW_AND_LEAVE_OPEN));
     631            pnl.add(rbChangesetHandlingOptions.get(ChangesetProcessingType.USE_EXISTING_AND_CLOSE));
     632            pnl.add(rbChangesetHandlingOptions.get(ChangesetProcessingType.USE_EXISTING_AND_LEAVE_OPEN));
     633
     634            for(ChangesetProcessingType type: ChangesetProcessingType.values()) {
     635                rbChangesetHandlingOptions.get(type).setVisible(false);
     636                bgChangesetHandlingOptions.add(rbChangesetHandlingOptions.get(type));
     637            }
     638            return pnl;
     639        }
     640
     641        protected JPanel buildChangesetControlPanel() {
     642            JPanel pnl = new JPanel();
     643            pnl.setLayout(new BoxLayout(pnl, BoxLayout.Y_AXIS));
     644            pnl.add(cbUseAtomicUpload = new JCheckBox(tr("upload all changes in one request")));
     645            cbUseAtomicUpload.setToolTipText(tr("Enable to upload all changes in one request, disable to use one request per changed primitive"));
     646            boolean useAtomicUpload = Main.pref.getBoolean("osm-server.atomic-upload", true);
     647            cbUseAtomicUpload.setSelected(useAtomicUpload);
     648            cbUseAtomicUpload.setEnabled(OsmApi.getOsmApi().hasSupportForDiffUploads());
     649
     650            pnl.add(buildChangesetHandlingControlPanel());
     651            return pnl;
     652        }
     653
     654        protected JPanel buildUploadControlPanel() {
     655            JPanel pnl = new JPanel();
     656            pnl.setLayout(new GridBagLayout());
     657            pnl.add(new JLabel(tr("Provide a brief comment for the changes you are uploading:")), GBC.eol().insets(0, 5, 10, 3));
     658            cmt = new SuggestingJHistoryComboBox();
     659            List<String> cmtHistory = new LinkedList<String>(Main.pref.getCollection(HISTORY_KEY, new LinkedList<String>()));
     660            cmt.setHistory(cmtHistory);
     661            pnl.add(cmt, GBC.eol().fill(GBC.HORIZONTAL));
     662
     663            // configuration options for atomic upload
     664            //
     665            pnl.add(buildChangesetControlPanel(), GBC.eol().fill(GridBagConstraints.HORIZONTAL));
     666            return pnl;
     667        }
     668
     669        protected void build() {
     670            setLayout(new GridBagLayout());
     671            GridBagConstraints gc = new GridBagConstraints();
     672            gc.fill = GridBagConstraints.BOTH;
     673            gc.weightx = 1.0;
     674            gc.weighty = 1.0;
     675            add(buildListsPanel(), gc);
     676
     677            southTabbedPane = new JTabbedPane();
     678            southTabbedPane.add(buildUploadControlPanel());
     679            tagEditorPanel = new TagEditorPanel();
     680            southTabbedPane.add(tagEditorPanel);
     681            southTabbedPane.setTitleAt(0, tr("Settings"));
     682            southTabbedPane.setTitleAt(1, tr("Tags of new changeset"));
     683            JPanel pnl = new JPanel();
     684            pnl.setLayout(new BorderLayout());
     685            pnl.add(southTabbedPane,BorderLayout.CENTER);
     686            gc.fill = GridBagConstraints.HORIZONTAL;
     687            gc.gridy = 1;
     688            gc.weightx = 1.0;
     689            gc.weighty = 0.0;
     690            add(pnl, gc);
     691        }
     692
     693
     694        protected UploadDialogPanel() {
     695            OsmPrimitivRenderer renderer = new OsmPrimitivRenderer();
     696
     697            lstAdd = new JList();
     698            lstAdd.setCellRenderer(renderer);
     699            lstAdd.setVisibleRowCount(Math.min(lstAdd.getModel().getSize(), 10));
     700
     701            lstUpdate = new JList();
     702            lstUpdate.setCellRenderer(renderer);
     703            lstUpdate.setVisibleRowCount(Math.min(lstUpdate.getModel().getSize(), 10));
     704
     705            lstDelete = new JList();
     706            lstDelete.setCellRenderer(renderer);
     707            lstDelete.setVisibleRowCount(Math.min(lstDelete.getModel().getSize(), 10));
     708            build();
     709        }
     710
     711        public void setUploadedPrimitives(Collection<OsmPrimitive> add, Collection<OsmPrimitive> update, Collection<OsmPrimitive> delete) {
     712            lstAdd.setListData(add.toArray());
     713            lstUpdate.setListData(update.toArray());
     714            lstDelete.setListData(delete.toArray());
     715
     716
     717            GridBagConstraints gcLabel = new GridBagConstraints();
     718            gcLabel.fill = GridBagConstraints.HORIZONTAL;
     719            gcLabel.weightx = 1.0;
     720            gcLabel.weighty = 0.0;
     721            gcLabel.anchor = GridBagConstraints.FIRST_LINE_START;
     722
     723            GridBagConstraints gcList = new GridBagConstraints();
     724            gcList.fill = GridBagConstraints.BOTH;
     725            gcList.weightx = 1.0;
     726            gcList.weighty = 1.0;
     727            gcList.anchor = GridBagConstraints.CENTER;
     728            pnlLists.removeAll();
     729            int y = -1;
     730            if (!add.isEmpty()) {
     731                y++;
     732                gcLabel.gridy = y;
     733                pnlLists.add(lblAdd = new JLabel(tr("Objects to add:")), gcLabel);
     734                y++;
     735                gcList.gridy = y;
     736                pnlLists.add(new JScrollPane(lstAdd), gcList);
     737            }
     738            if (!update.isEmpty()) {
     739                y++;
     740                gcLabel.gridy = y;
     741                pnlLists.add(lblUpdate = new JLabel(tr("Objects to modify:")), gcLabel);
     742                y++;
     743                gcList.gridy = y;
     744                pnlLists.add(new JScrollPane(lstUpdate), gcList);
     745            }
     746            if (!delete.isEmpty()) {
     747                y++;
     748                gcLabel.gridy = y;
     749                pnlLists.add(lblDelete = new JLabel(tr("Objects to delete:")), gcLabel);
     750                y++;
     751                gcList.gridy = y;
     752                pnlLists.add(new JScrollPane(lstDelete), gcList);
     753            }
     754        }
     755
     756        public boolean hasChangesetComment() {
     757            if (!getChangesetProcessingType().isUseNew())
     758                return true;
     759            return cmt.getText().trim().length() >= 3;
     760        }
     761
     762        public void rememberUserInput() {
     763            // store the history of comments
     764            cmt.addCurrentItemToHistory();
     765            Main.pref.putCollection(HISTORY_KEY, cmt.getHistory());
     766            Main.pref.put("osm-server.atomic-upload", cbUseAtomicUpload.isSelected());
     767        }
     768
     769        public void startUserInput() {
     770            tagEditorPanel.initAutoCompletion(Main.main.getEditLayer());
     771            initChangesetProcessingType();
     772            cmt.getEditor().selectAll();
     773            cmt.requestFocus();
     774        }
     775
     776        public ChangesetProcessingType getChangesetProcessingType() {
     777            ChangesetProcessingType changesetProcessingType = null;
     778            for (ChangesetProcessingType type: ChangesetProcessingType.values()) {
     779                if (rbChangesetHandlingOptions.get(type).isSelected()) {
     780                    changesetProcessingType = type;
     781                    break;
     782                }
     783            }
     784            return changesetProcessingType == null ?
     785                    ChangesetProcessingType.USE_NEW_AND_CLOSE :
     786                        changesetProcessingType;
     787        }
     788
     789        public Changeset getChangeset() {
     790            Changeset changeset = new Changeset();
     791            tagEditorPanel.getModel().applyToPrimitive(changeset);
     792            changeset.put("comment", cmt.getText());
     793            return changeset;
     794        }
     795
     796        protected void initChangesetProcessingType() {
     797            for (ChangesetProcessingType type: ChangesetProcessingType.values()) {
     798                // show options for new changeset, disable others
     799                //
     800                rbChangesetHandlingOptions.get(type).setVisible(type.isUseNew());
     801            }
     802            if (OsmApi.getOsmApi().getCurrentChangeset() != null) {
     803                Changeset cs = OsmApi.getOsmApi().getCurrentChangeset();
     804                for (ChangesetProcessingType type: ChangesetProcessingType.values()) {
     805                    // show options for using existing changeset
     806                    //
     807                    if (!type.isUseNew()) {
     808                        rbChangesetHandlingOptions.get(type).setVisible(true);
     809                    }
     810                }
     811                JRadioButton rb = rbChangesetHandlingOptions.get(ChangesetProcessingType.USE_EXISTING_AND_CLOSE);
     812                rb.setText(tr("Use the existing changeset {0} and close it after upload",cs.getId()));
     813                rb.setToolTipText(tr("Select to upload to the existing changeset {0} and to close the changeset after this upload",cs.getId()));
     814
     815                rb = rbChangesetHandlingOptions.get(ChangesetProcessingType.USE_EXISTING_AND_LEAVE_OPEN);
     816                rb.setText(tr("Use the existing changeset {0} and leave it open",cs.getId()));
     817                rb.setToolTipText(tr("Select to upload to the existing changeset {0} and to leave the changeset open for further uploads",cs.getId()));
     818
     819                rbChangesetHandlingOptions.get(getChangesetProcessingType()).setSelected(true);
     820
     821            } else {
     822                ChangesetProcessingType type = getChangesetProcessingType();
     823                if (!type.isUseNew()) {
     824                    type = ChangesetProcessingType.USE_NEW_AND_CLOSE;
     825                }
     826                rbChangesetHandlingOptions.get(type).setSelected(true);
     827            }
     828        }
     829
     830        class ChangesetProcessingTypeChangedAction implements ActionListener {
     831            public void actionPerformed(ActionEvent e) {
     832                ChangesetProcessingType type = getChangesetProcessingType();
     833                if (type.isUseNew()) {
     834                    tagEditorPanel.setEnabled(true);
     835                    southTabbedPane.setTitleAt(1, tr("Tags of new changeset"));
     836                    cmt.setEnabled(true);
     837                } else {
     838                    tagEditorPanel.setEnabled(false);
     839                    cmt.setEnabled(false);
     840                    Changeset cs = OsmApi.getOsmApi().getCurrentChangeset();
     841                    if (cs != null) {
     842                        tagEditorPanel.getModel().initFromPrimitive(cs);
     843                        southTabbedPane.setTitleAt(1, tr("Tags of changeset {0} (read-only)", cs.getId()));
     844                        cmt.setText(cs.get("comment" == null ? "" : cs.get("comment")));
     845                    }
     846                }
    568847            }
    569848        }
  • /trunk/src/org/openstreetmap/josm/actions/mapmode/DeleteAction.java

    r2024 r2060  
    44import static org.openstreetmap.josm.tools.I18n.tr;
    55
     6import java.awt.AWTEvent;
     7import java.awt.Cursor;
     8import java.awt.EventQueue;
     9import java.awt.Toolkit;
     10import java.awt.event.AWTEventListener;
    611import java.awt.event.ActionEvent;
    712import java.awt.event.InputEvent;
    813import java.awt.event.KeyEvent;
    914import java.awt.event.MouseEvent;
     15import java.util.Collection;
    1016import java.util.Collections;
     17import java.util.HashSet;
    1118
    1219import org.openstreetmap.josm.Main;
    1320import org.openstreetmap.josm.command.Command;
    1421import org.openstreetmap.josm.command.DeleteCommand;
     22import org.openstreetmap.josm.data.osm.Node;
    1523import org.openstreetmap.josm.data.osm.OsmPrimitive;
    1624import org.openstreetmap.josm.data.osm.Relation;
     25import org.openstreetmap.josm.data.osm.Way;
    1726import org.openstreetmap.josm.data.osm.WaySegment;
    1827import org.openstreetmap.josm.gui.MapFrame;
     
    3847 * @author imi
    3948 */
    40 public class DeleteAction extends MapMode {
     49
     50/**
     51 * This class contains stubs for highlighting affected primitives when affected.
     52 * However, way segments can be deleted as well, but cannot be highlighted
     53 * alone. If the highlight feature for this delete action is to be implemented
     54 * properly, highlighting way segments must be possible first. --xeen, 2009-09-02
     55 */
     56public class DeleteAction extends MapMode implements AWTEventListener {
     57    //private boolean drawTargetHighlight;
     58    private boolean drawTargetCursor;
     59    //private Collection<? extends OsmPrimitive> oldPrims = null;
     60
     61    // Cache previous mouse event (needed when only the modifier keys are
     62    // pressed but the mouse isn't moved)
     63    private MouseEvent oldEvent = null;
     64
     65    private enum Cursors {
     66        none,
     67        node,
     68        segment,
     69        way_node_only,
     70        way_normal,
     71        way_only;
     72
     73        private Cursor c = null;
     74        // This loads and caches the cursor for each
     75        public Cursor cursor() {
     76            if(c == null) {
     77                String nm = "delete_" + this.name().toLowerCase();
     78                // "None" has no special icon
     79                nm = nm.equals("delete_none") ? "delete" : nm;
     80                this.c = ImageProvider.getCursor("normal", nm);
     81            }
     82            return c;
     83        }
     84    }
     85    private Cursors currCursor = Cursors.none;
    4186
    4287    /**
     
    57102        if (!isEnabled())
    58103            return;
     104        //drawTargetHighlight = Main.pref.getBoolean("draw.target-highlight", true);
     105        drawTargetCursor = Main.pref.getBoolean("draw.target-cursor", true);
     106
    59107        Main.map.mapView.addMouseListener(this);
     108        Main.map.mapView.addMouseMotionListener(this);
     109        // This is required to update the cursors when ctrl/shift/alt is pressed
     110        try {
     111            Toolkit.getDefaultToolkit().addAWTEventListener(this, AWTEvent.KEY_EVENT_MASK);
     112        } catch (SecurityException ex) {}
     113
     114        currCursor = Cursors.none;
    60115    }
    61116
     
    63118        super.exitMode();
    64119        Main.map.mapView.removeMouseListener(this);
     120        Main.map.mapView.removeMouseMotionListener(this);
     121        try {
     122            Toolkit.getDefaultToolkit().removeAWTEventListener(this);
     123        } catch (SecurityException ex) {}
    65124    }
    66125
     
    94153
    95154    /**
     155     * Listen to mouse move to be able to update the cursor (and highlights)
     156     * @param MouseEvent The mouse event that has been captured
     157     */
     158    @Override public void mouseMoved(MouseEvent e) {
     159        oldEvent = e;
     160        updateCursor(e, e.getModifiers());
     161    }
     162
     163    /**
     164     * This function handles all work related to updating the cursor and
     165     * highlights. For now, only the cursor is enabled because highlighting
     166     * requires WaySegment to be highlightable.
     167     *
     168     * Normally the mouse event also contains the modifiers. However, when the
     169     * mouse is not moved and only modifier keys are pressed, no mouse event
     170     * occurs. We can use AWTEvent to catch those but still lack a proper
     171     * mouseevent. Instead we copy the previous event and only update the
     172     * modifiers.
     173     *
     174     * @param MouseEvent
     175     * @parm int modifiers
     176     */
     177    private void updateCursor(MouseEvent e, int modifiers) {
     178        if(!Main.map.mapView.isActiveLayerVisible() || e == null)
     179            return;
     180
     181        // Clean old highlights
     182        //cleanOldHighlights();
     183
     184        Command c = buildDeleteCommands(e, modifiers, true);
     185        if(c == null) {
     186            setCursor(Cursors.none);
     187            return;
     188        }
     189
     190        Collection<OsmPrimitive> prims = new HashSet<OsmPrimitive>();
     191        Collection<OsmPrimitive> mods = new HashSet<OsmPrimitive>();
     192        c.fillModifiedData(mods, prims, prims);
     193
     194        if(prims.size() == 0 && mods.size() == 0) {
     195            // Default-Cursor
     196            setCursor(Cursors.none);
     197            return;
     198        }
     199
     200        // There are no deleted parts if solely a way segment is deleted
     201        // This is no the case when actually deleting only a segment but that
     202        // segment happens to be the whole way. This is an acceptable error
     203        // though
     204        if(prims.size() == 0) {
     205            setCursor(Cursors.segment);
     206        } else if(prims.size() == 1 && prims.toArray()[0] instanceof Node) {
     207            setCursor(Cursors.node);
     208        } else if(prims.size() == 1 && prims.toArray()[0] instanceof Way) {
     209            setCursor(Cursors.way_only);
     210        } else {
     211            // Decide between non-accel click where "useless" nodes are deleted
     212            // and ctrl-click where nodes and ways are deleted
     213            boolean ctrl = (modifiers & ActionEvent.CTRL_MASK) != 0;
     214            if(ctrl) {
     215                setCursor(Cursors.way_node_only);
     216            } else {
     217                setCursor(Cursors.way_normal);
     218            }
     219
     220        }
     221
     222        // Needs to implement WaySegment highlight first
     223        /*if(drawTargetHighlight) {
     224            // Add new highlights
     225            for(OsmPrimitive p : prims) {
     226                p.highlighted = true;
     227            }
     228            oldPrims = prims;
     229        }*/
     230
     231        // We only need to repaint if the highlights changed
     232        //Main.map.mapView.repaint();
     233    }
     234
     235    /**
     236     * Small helper function that cleans old highlights
     237     */
     238    /*private void cleanOldHighlights() {
     239        if(oldPrims == null)
     240            return;
     241        for(OsmPrimitive p: oldPrims) {
     242            p.highlighted = false;
     243        }
     244    }*/
     245
     246    /**
    96247     * If user clicked with the left button, delete the nearest object.
    97248     * position.
     
    107258        Main.map.mapView.requestFocus();
    108259
    109         boolean ctrl = (e.getModifiers() & ActionEvent.CTRL_MASK) != 0;
    110         boolean shift = (e.getModifiers() & ActionEvent.SHIFT_MASK) != 0;
    111         boolean alt = (e.getModifiers() & (ActionEvent.ALT_MASK|InputEvent.ALT_GRAPH_MASK)) != 0;
     260        Command c = buildDeleteCommands(e, e.getModifiers(), false);
     261        if (c != null) {
     262            Main.main.undoRedo.add(c);
     263        }
     264
     265        getCurrentDataSet().setSelected();
     266        Main.map.mapView.repaint();
     267    }
     268
     269    @Override public String getModeHelpText() {
     270        return tr("Click to delete. Shift: delete way segment. Alt: don't delete unused nodes when deleting a way. Ctrl: delete referring objects.");
     271    }
     272
     273    @Override public boolean layerIsSupported(Layer l) {
     274        return l instanceof OsmDataLayer;
     275    }
     276
     277    @Override
     278    protected void updateEnabledState() {
     279        setEnabled(Main.map != null && Main.map.mapView != null && Main.map.mapView.isActiveLayerDrawable());
     280    }
     281
     282    /**
     283     * Deletes the relation in the context of the given layer. Also notifies
     284     * {@see RelationDialogManager} and {@see OsmDataLayer#fireDataChange()} events.
     285     *
     286     * @param layer the layer in whose context the relation is deleted. Must not be null.
     287     * @param toDelete  the relation to be deleted. Must  not be null.
     288     * @exception IllegalArgumentException thrown if layer is null
     289     * @exception IllegalArgumentException thrown if toDelete is nul
     290     */
     291    public static void deleteRelation(OsmDataLayer layer, Relation toDelete) {
     292        if (layer == null)
     293            throw new IllegalArgumentException(tr("parameter ''{0}'' must not be null", "layer"));
     294        if (toDelete == null)
     295            throw new IllegalArgumentException(tr("parameter ''{0}'' must not be null", "toDelete"));
     296
     297        Command cmd = DeleteCommand.delete(layer, Collections.singleton(toDelete));
     298        if (cmd != null) {
     299            // cmd can be null if the user cancels dialogs DialogCommand displays
     300            Main.main.undoRedo.add(cmd);
     301            RelationDialogManager.getRelationDialogManager().close(layer, toDelete);
     302            layer.fireDataChange();
     303        }
     304    }
     305
     306    /**
     307     * This function takes any mouse event argument and builds the list of elements
     308     * that should be deleted but does not actually delete them.
     309     * @param e MouseEvent from which modifiers and position are taken
     310     * @param int modifiers For explanation: @see updateCursor
     311     * @param Simulate Set to true if the user should be bugged with additional
     312     *        dialogs
     313     * @return
     314     */
     315    private Command buildDeleteCommands(MouseEvent e, int modifiers, boolean simulate) {
     316        // Note: CTRL is the only modifier that is checked in MouseMove, don't
     317        // forget updating it there
     318        boolean ctrl = (modifiers & ActionEvent.CTRL_MASK) != 0;
     319        boolean shift = (modifiers & ActionEvent.SHIFT_MASK) != 0;
     320        boolean alt = (modifiers & (ActionEvent.ALT_MASK|InputEvent.ALT_GRAPH_MASK)) != 0;
    112321
    113322        OsmPrimitive sel = Main.map.mapView.getNearestNode(e.getPoint());
     
    119328                    c = DeleteCommand.deleteWaySegment(getEditLayer(),ws);
    120329                } else if (ctrl) {
    121                     c = DeleteCommand.deleteWithReferences(getEditLayer(),Collections.singleton((OsmPrimitive)ws.way));
     330                    c = DeleteCommand.deleteWithReferences(getEditLayer(),Collections.singleton((OsmPrimitive)ws.way),true);
    122331                } else {
    123                     c = DeleteCommand.delete(getEditLayer(),Collections.singleton((OsmPrimitive)ws.way), !alt);
     332                    c = DeleteCommand.delete(getEditLayer(),Collections.singleton((OsmPrimitive)ws.way), !alt, simulate);
    124333                }
    125334            }
     
    127336            c = DeleteCommand.deleteWithReferences(getEditLayer(),Collections.singleton(sel));
    128337        } else {
    129             c = DeleteCommand.delete(getEditLayer(),Collections.singleton(sel), !alt);
    130         }
    131         if (c != null) {
    132             Main.main.undoRedo.add(c);
    133         }
    134 
    135         getCurrentDataSet().setSelected();
    136         Main.map.mapView.repaint();
    137     }
    138 
    139     @Override public String getModeHelpText() {
    140         return tr("Click to delete. Shift: delete way segment. Alt: don't delete unused nodes when deleting a way. Ctrl: delete referring objects.");
    141     }
    142 
    143     @Override public boolean layerIsSupported(Layer l) {
    144         return l instanceof OsmDataLayer;
    145     }
    146 
    147     @Override
    148     protected void updateEnabledState() {
    149         setEnabled(Main.map != null && Main.map.mapView != null && Main.map.mapView.isActiveLayerDrawable());
    150     }
    151 
    152     /**
    153      * Deletes the relation in the context of the given layer. Also notifies
    154      * {@see RelationDialogManager} and {@see OsmDataLayer#fireDataChange()} events.
    155      *
    156      * @param layer the layer in whose context the relation is deleted. Must not be null.
    157      * @param toDelete  the relation to be deleted. Must  not be null.
    158      * @exception IllegalArgumentException thrown if layer is null
    159      * @exception IllegalArgumentException thrown if toDelete is nul
    160      */
    161     public static void deleteRelation(OsmDataLayer layer, Relation toDelete) {
    162         if (layer == null)
    163             throw new IllegalArgumentException(tr("parameter ''{0}'' must not be null", "layer"));
    164         if (toDelete == null)
    165             throw new IllegalArgumentException(tr("parameter ''{0}'' must not be null", "toDelete"));
    166         if (toDelete == null)
    167             return;
    168         Command cmd = DeleteCommand.delete(layer, Collections.singleton(toDelete));
    169         if (cmd != null) {
    170             // cmd can be null if the user cancels dialogs DialogCommand displays
    171             //
    172             Main.main.undoRedo.add(cmd);
    173             RelationDialogManager.getRelationDialogManager().close(layer, toDelete);
    174             layer.fireDataChange();
    175         }
     338            c = DeleteCommand.delete(getEditLayer(),Collections.singleton(sel), !alt, simulate);
     339        }
     340
     341        return c;
     342    }
     343
     344    /**
     345     * This function sets the given cursor in a safe way. This implementation
     346     * differs from the on in DrawAction (it is favorable, too).
     347     * FIXME: Update DrawAction to use this "setCursor-style" and move function
     348     * to MapMode.
     349     * @param c
     350     */
     351    private void setCursor(final Cursors c) {
     352        if(currCursor.equals(c) || (!drawTargetCursor && currCursor.equals(Cursors.none)))
     353            return;
     354        try {
     355            // We invoke this to prevent strange things from happening
     356            EventQueue.invokeLater(new Runnable() {
     357                public void run() {
     358                    // Don't change cursor when mode has changed already
     359                    if(!(Main.map.mapMode instanceof DeleteAction))
     360                        return;
     361
     362                    Main.map.mapView.setCursor(c.cursor());
     363                    //System.out.println("Set cursor to: " + c.name());
     364                }
     365            });
     366            currCursor = c;
     367        } catch(Exception e) {}
     368    }
     369
     370    /**
     371     * This is required to update the cursors when ctrl/shift/alt is pressed
     372     */
     373    public void eventDispatched(AWTEvent e) {
     374        // We don't have a mouse event, so we pass the old mouse event but the
     375        // new modifiers.
     376        updateCursor(oldEvent, ((InputEvent)e).getModifiers());
    176377    }
    177378}
  • /trunk/src/org/openstreetmap/josm/actions/mapmode/DrawAction.java

    r2024 r2060  
    765765        Way way = null;
    766766        for (Way w : getCurrentDataSet().ways) {
    767             if (w.deleted || w.incomplete || w.getNodesCount() < 1) {
     767            if (w.isDeleted() || w.incomplete || w.getNodesCount() < 1) {
    768768                continue;
    769769            }
  • /trunk/src/org/openstreetmap/josm/actions/mapmode/SelectAction.java

    r2024 r2060  
    465465                    if(s.size() > max)
    466466                    {
    467                         if(1 != new ExtendedDialog(Main.parent, tr("Move elements"),
    468                                 tr("You did move more than {0} elements. "
    469                                         + "Moving a large number of elements is often an error.\n"
    470                                         + "Really move them?", max),
    471                                         new String[] {tr("Move them"), tr("Undo move")},
    472                                         new String[] {"reorder.png", "cancel.png"}).getValue())
     467                        ExtendedDialog ed = new ExtendedDialog(
     468                                Main.parent,
     469                                tr("Move elements"),
     470                                new String[] {tr("Move them"), tr("Undo move")});
     471                        ed.setButtonIcons(new String[] {"reorder.png", "cancel.png"});
     472                        ed.setContent(tr("You moved more than {0} elements. "
     473                                + "Moving a large number of elements is often an error.\n"
     474                                + "Really move them?", max));
     475                        ed.toggleEnable("movedManyElements");
     476                        ed.setToggleCheckboxText(tr("Always move and don't show dialog again"));
     477                        ed.showDialog();
     478
     479                        if(ed.getValue() != 1 && ed.getValue() != ExtendedDialog.DialogNotShown)
    473480                        {
    474481                            Main.main.undoRedo.undo();
  • /trunk/src/org/openstreetmap/josm/actions/search/SearchCompiler.java

    r2024 r2060  
    227227
    228228            switch (mode) {
    229             case NONE:
    230                 return false;
    231             case MISSING_KEY:
    232                 return osm.get(key) == null;
    233             case ANY:
    234                 return true;
    235             case ANY_VALUE:
    236                 return osm.get(key) != null;
    237             case ANY_KEY:
    238                 for (String v:osm.getKeys().values()) {
    239                     if (v.equals(value))
    240                         return true;
    241                 }
    242                 return false;
    243             case EXACT:
    244                 return value.equals(osm.get(key));
    245             case ANY_KEY_REGEXP:
    246                 for (String v:osm.getKeys().values()) {
    247                     if (valuePattern.matcher(v).matches())
    248                         return true;
    249                 }
    250                 return false;
    251             case ANY_VALUE_REGEXP:
    252             case EXACT_REGEXP:
    253                 for (Entry<String, String> entry:osm.entrySet()) {
    254                     if (keyPattern.matcher(entry.getKey()).matches()) {
    255                         if (mode == Mode.ANY_VALUE_REGEXP
    256                                 || valuePattern.matcher(entry.getValue()).matches())
     229                case NONE:
     230                    return false;
     231                case MISSING_KEY:
     232                    return osm.get(key) == null;
     233                case ANY:
     234                    return true;
     235                case ANY_VALUE:
     236                    return osm.get(key) != null;
     237                case ANY_KEY:
     238                    for (String v:osm.getKeys().values()) {
     239                        if (v.equals(value))
    257240                            return true;
    258241                    }
    259                 }
    260                 return false;
    261             case MISSING_KEY_REGEXP:
    262                 for (String k:osm.keySet()) {
    263                     if (keyPattern.matcher(k).matches())
    264                         return false;
    265                 }
    266                 return true;
     242                    return false;
     243                case EXACT:
     244                    return value.equals(osm.get(key));
     245                case ANY_KEY_REGEXP:
     246                    for (String v:osm.getKeys().values()) {
     247                        if (valuePattern.matcher(v).matches())
     248                            return true;
     249                    }
     250                    return false;
     251                case ANY_VALUE_REGEXP:
     252                case EXACT_REGEXP:
     253                    for (Entry<String, String> entry:osm.entrySet()) {
     254                        if (keyPattern.matcher(entry.getKey()).matches()) {
     255                            if (mode == Mode.ANY_VALUE_REGEXP
     256                                    || valuePattern.matcher(entry.getValue()).matches())
     257                                return true;
     258                        }
     259                    }
     260                    return false;
     261                case MISSING_KEY_REGEXP:
     262                    for (String k:osm.keySet()) {
     263                        if (keyPattern.matcher(k).matches())
     264                            return false;
     265                    }
     266                    return true;
    267267            }
    268268            throw new AssertionError("Missed state");
     
    402402    private static class Modified extends Match {
    403403        @Override public boolean match(OsmPrimitive osm) {
    404             return osm.modified || osm.id == 0;
     404            return osm.isModified() || osm.getId() == 0;
    405405        }
    406406        @Override public String toString() {return "modified";}
  • /trunk/src/org/openstreetmap/josm/actions/search/SelectionWebsiteLoader.java

    r2024 r2060  
    4848            Map<Long, String> ids = idReader.parseIds(in);
    4949            for (OsmPrimitive osm : Main.main.getCurrentDataSet().allNonDeletedPrimitives()) {
    50                 if (ids.containsKey(osm.id) && osm.getClass().getName().toLowerCase().endsWith(ids.get(osm.id))) {
     50                if (ids.containsKey(osm.getId()) && osm.getClass().getName().toLowerCase().endsWith(ids.get(osm.getId()))) {
    5151                    if (mode == SearchAction.SearchMode.remove) {
    5252                        sel.remove(osm);
  • /trunk/src/org/openstreetmap/josm/command/ChangeCommand.java

    r2024 r2060  
    3636        super.executeCommand();
    3737        osm.cloneFrom(newOsm);
    38         osm.modified = true;
     38        osm.setModified(true);
    3939        return true;
    4040    }
     
    4747        String msg = "";
    4848        switch(OsmPrimitiveType.from(osm)) {
    49         case NODE: msg = marktr("Change node {0}"); break;
    50         case WAY: msg = marktr("Change way {0}"); break;
    51         case RELATION: msg = marktr("Change relation {0}"); break;
     49            case NODE: msg = marktr("Change node {0}"); break;
     50            case WAY: msg = marktr("Change way {0}"); break;
     51            case RELATION: msg = marktr("Change relation {0}"); break;
    5252        }
    5353        return new DefaultMutableTreeNode(
  • /trunk/src/org/openstreetmap/josm/command/ChangePropertyCommand.java

    r2024 r2060  
    7777        if (value == null) {
    7878            for (OsmPrimitive osm : objects) {
    79                 osm.modified = true;
     79                osm.setModified(true);
    8080                osm.remove(key);
    8181            }
    8282        } else {
    8383            for (OsmPrimitive osm : objects) {
    84                 osm.modified = true;
     84                osm.setModified(true);
    8585                osm.put(key, value);
    8686            }
  • /trunk/src/org/openstreetmap/josm/command/ChangeRelationMemberRoleCommand.java

    r2024 r2060  
    5151        relation.getMember(position).role = newRole;
    5252
    53         oldModified = relation.modified;
    54         relation.modified = true;
     53        oldModified = relation.isModified();
     54        relation.setModified(true);
    5555        return true;
    5656    }
     
    5858    @Override public void undoCommand() {
    5959        relation.getMember(position).role = oldRole;
    60         relation.modified = oldModified;
     60        relation.setModified(oldModified);
    6161    }
    6262
  • /trunk/src/org/openstreetmap/josm/command/Command.java

    r2024 r2060  
    8989            e.getKey().cloneFrom(e.getValue());
    9090        }
    91         getLayer().setModified(true);
    9291    }
    9392
     
    114113        if (o != null)
    115114            return o;
    116         Main.debug("unable to find osm with id: " + osm.id + " hashCode: " + osm.hashCode());
     115        Main.debug("unable to find osm with id: " + osm.getId() + " hashCode: " + osm.hashCode());
    117116        for (OsmPrimitive t : cloneMap.keySet()) {
    118117            OsmPrimitive to = cloneMap.get(t);
    119             Main.debug("now: " + t.id + " hashCode: " + t.hashCode());
    120             Main.debug("orig: " + to.id + " hashCode: " + to.hashCode());
     118            Main.debug("now: " + t.getId() + " hashCode: " + t.hashCode());
     119            Main.debug("orig: " + to.getId() + " hashCode: " + to.hashCode());
    121120        }
    122121        return o;
  • /trunk/src/org/openstreetmap/josm/command/CoordinateConflictResolveCommand.java

    r2024 r2060  
    4545        return new DefaultMutableTreeNode(
    4646                new JLabel(
    47                         tr("Resolve conflicts in coordinates in {0}",conflict.getMy().id),
     47                        tr("Resolve conflicts in coordinates in {0}",conflict.getMy().getId()),
    4848                        ImageProvider.get("data", "object"),
    4949                        JLabel.HORIZONTAL
  • /trunk/src/org/openstreetmap/josm/command/DeleteCommand.java

    r2024 r2060  
    4343 */
    4444public class DeleteCommand extends Command {
    45 
    4645    /**
    4746     * The primitives that get deleted.
     
    157156     * If a way is deleted, only the way and no nodes are deleted.
    158157     *
     158     * @param layer
    159159     * @param selection The list of all object to be deleted.
     160     * @param simulate  Set to true if the user should not be bugged with additional dialogs
    160161     * @return command A command to perform the deletions, or null of there is nothing to delete.
    161162     */
    162     public static Command deleteWithReferences(OsmDataLayer layer, Collection<? extends OsmPrimitive> selection) {
     163    public static Command deleteWithReferences(OsmDataLayer layer, Collection<? extends OsmPrimitive> selection, boolean simulate) {
    163164        CollectBackReferencesVisitor v = new CollectBackReferencesVisitor(layer.data);
    164165        for (OsmPrimitive osm : selection) {
     
    168169        if (v.data.isEmpty())
    169170            return null;
    170         if (!checkAndConfirmOutlyingDeletes(layer,v.data))
     171        if (!checkAndConfirmOutlyingDeletes(layer,v.data) && !simulate)
    171172            return null;
    172173        return new DeleteCommand(layer,v.data);
    173174    }
    174175
    175     private static int testRelation(Relation ref, OsmPrimitive osm) {
     176    public static Command deleteWithReferences(OsmDataLayer layer, Collection<? extends OsmPrimitive> selection) {
     177        return deleteWithReferences(layer, selection, false);
     178    }
     179
     180    private static int testRelation(Relation ref, OsmPrimitive osm, boolean simulate) {
     181        // If this delete action is simulated, do not bug the user with dialogs
     182        // and assume the relations should be deleted
     183        if(simulate)
     184            return 1;
     185
    176186        String role = new String();
    177187        for (RelationMember m : ref.getMembers()) {
     
    181191            }
    182192        }
    183         if (role.length() > 0)
    184             return new ExtendedDialog(Main.parent, tr("Conflicting relation"), tr(
    185                     "Selection \"{0}\" is used by relation \"{1}\" with role {2}.\nDelete from relation?",
    186                     osm.getDisplayName(DefaultNameFormatter.getInstance()), ref.getDisplayName(DefaultNameFormatter.getInstance()), role), new String[] { tr("Delete from relation"),
    187                 tr("Cancel") }, new String[] { "dialogs/delete.png", "cancel.png" }).getValue();
    188         else
    189             return new ExtendedDialog(Main.parent, tr("Conflicting relation"), tr(
    190                     "Selection \"{0}\" is used by relation \"{1}\".\nDelete from relation?",
    191                     osm.getDisplayName(DefaultNameFormatter.getInstance()),
    192                     ref.getDisplayName(DefaultNameFormatter.getInstance())), new String[] { tr("Delete from relation"), tr("Cancel") }, new String[] {
    193                 "dialogs/delete.png", "cancel.png" }).getValue();
     193        ExtendedDialog dialog = new ExtendedDialog(
     194                Main.parent,
     195                tr("Conflicting relation"),
     196                new String[] { tr("Delete from relation"),tr("Cancel") }
     197        );
     198        dialog.setButtonIcons( new String[] { "dialogs/delete.png", "cancel.png" });
     199        if (role.length() > 0) {
     200            dialog.setContent(
     201                    tr(
     202                            "<html>Selection \"{0}\" is used by relation \"{1}\" with role {2}.<br>Delete from relation?</html>",
     203                            osm.getDisplayName(DefaultNameFormatter.getInstance()),
     204                            ref.getDisplayName(DefaultNameFormatter.getInstance()),
     205                            role
     206                    )
     207            );
     208            dialog.showDialog();
     209            return dialog.getValue();
     210        } else {
     211            dialog.setContent(
     212                    tr(
     213                            "<html>Selection \"{0}\" is used by relation \"{1}\".<br>Delete from relation?</html>",
     214                            osm.getDisplayName(DefaultNameFormatter.getInstance()),
     215                            ref.getDisplayName(DefaultNameFormatter.getInstance())
     216                    )
     217            );
     218            dialog.showDialog();
     219            return dialog.getValue();
     220        }
    194221    }
    195222
    196223    public static Command delete(OsmDataLayer layer, Collection<? extends OsmPrimitive> selection) {
    197         return delete(layer, selection, true);
     224        return delete(layer, selection, true, false);
    198225    }
    199226
     
    243270     * @param selection The objects to delete.
    244271     * @param alsoDeleteNodesInWay <code>true</code> if nodes should be deleted as well
     272     * @param simulate Set to true if the user should not be bugged with additional questions
    245273     * @return command a command to perform the deletions, or null if there is nothing to delete.
    246274     */
    247     public static Command delete(OsmDataLayer layer, Collection<? extends OsmPrimitive> selection, boolean alsoDeleteNodesInWay) {
     275    public static Command delete(OsmDataLayer layer, Collection<? extends OsmPrimitive> selection,
     276            boolean alsoDeleteNodesInWay) {
     277        return delete(layer, selection, alsoDeleteNodesInWay, false);
     278    }
     279
     280    public static Command delete(OsmDataLayer layer, Collection<? extends OsmPrimitive> selection,
     281            boolean alsoDeleteNodesInWay, boolean simulate) {
    248282        if (selection.isEmpty())
    249283            return null;
     
    260294        }
    261295
    262         if (!checkAndConfirmOutlyingDeletes(layer,primitivesToDelete))
     296        if (!simulate && !checkAndConfirmOutlyingDeletes(layer,primitivesToDelete))
    263297            return null;
    264298
     
    273307                    waysToBeChanged.add((Way) ref);
    274308                } else if (ref instanceof Relation) {
    275                     if (testRelation((Relation) ref, osm) == 1) {
     309                    if (testRelation((Relation) ref, osm, simulate) == 1) {
    276310                        Collection<OsmPrimitive> relset = relationsToBeChanged.get(ref);
    277311                        if (relset == null) {
     
    314348                        }
    315349                        if (!found) {
    316                             if (testRelation((Relation) ref, w) == 1) {
     350                            if (testRelation((Relation) ref, w, simulate) == 1) {
    317351                                relset.add(w);
    318352                                relationsToBeChanged.put(ref, relset);
     
    355389            }
    356390            Way w = (Way) primitive;
    357             if (w.id == 0) { // new ways with id == 0 are fine,
     391            if (w.getId() == 0) { // new ways with id == 0 are fine,
    358392                continue; // process existing ways only
    359393            }
     
    363397            // nodes ...
    364398            for (Node n : wnew.getNodes()) {
    365                 if (n.id != 0 || !primitivesToDelete.contains(n)) {
     399                if (n.getId() != 0 || !primitivesToDelete.contains(n)) {
    366400                    nodesToKeep.add(n);
    367401                }
     
    426460        if (a != null) {
    427461            for (OsmPrimitive osm : primitivesToDelete) {
    428                 if (osm instanceof Node && osm.id != 0) {
     462                if (osm instanceof Node && osm.getId() != 0) {
    429463                    Node n = (Node) osm;
    430464                    if (!a.contains(n.getCoor())) {
  • /trunk/src/org/openstreetmap/josm/command/DeletedStateConflictResolveCommand.java

    r2024 r2060  
    4545        return new DefaultMutableTreeNode(
    4646                new JLabel(
    47                         tr("Resolve conflicts in deleted state in {0}",conflict.getMy().id),
     47                        tr("Resolve conflicts in deleted state in {0}",conflict.getMy().getId()),
    4848                        ImageProvider.get("data", "object"),
    4949                        JLabel.HORIZONTAL
     
    6262
    6363        if (decision.equals(MergeDecisionType.KEEP_MINE)) {
    64             if (conflict.getMy().deleted) {
     64            if (conflict.getMy().isDeleted()) {
    6565                // because my was involved in a conflict it my still be referred
    6666                // to from a way or a relation. Fix this now.
     
    6969            }
    7070        } else if (decision.equals(MergeDecisionType.KEEP_THEIR)) {
    71             if (conflict.getTheir().deleted) {
     71            if (conflict.getTheir().isDeleted()) {
    7272                layer.data.unlinkReferencesToPrimitive(conflict.getMy());
    7373                conflict.getMy().delete(true);
    7474            } else {
    75                 conflict.getMy().deleted = conflict.getTheir().deleted;
     75                conflict.getMy().delete(conflict.getTheir().isDeleted());
    7676            }
    7777        } else
  • /trunk/src/org/openstreetmap/josm/command/MoveCommand.java

    r2024 r2060  
    6969            OldState os = new OldState();
    7070            os.latlon = new LatLon(n.getCoor());
    71             os.modified = n.modified;
     71            os.modified = n.isModified();
    7272            oldState.add(os);
    7373        }
     
    9393        for (Node n : nodes) {
    9494            n.setEastNorth(n.getEastNorth().add(x, y));
    95             n.modified = true;
     95            n.setModified(true);
    9696        }
    9797        return true;
     
    103103            OldState os = it.next();
    104104            n.setCoor(os.latlon);
    105             n.modified = os.modified;
     105            n.setModified(os.modified);
    106106        }
    107107    }
  • /trunk/src/org/openstreetmap/josm/data/Preferences.java

    r2024 r2060  
    1313import java.io.OutputStreamWriter;
    1414import java.io.PrintWriter;
     15import java.nio.channels.FileChannel;
    1516import java.util.ArrayList;
    1617import java.util.Arrays;
     
    4445
    4546    /**
    46      * Internal storage for the preferenced directory.
     47     * Internal storage for the preference directory.
    4748     * Do not access this variable directly!
    4849     * @see #getPreferencesDirFile()
     
    118119    }
    119120
     121    public File getPreferenceFile() {
     122        return new File(getPreferencesDirFile(), "preferences");
     123    }
     124
    120125    public File getPluginsDirFile() {
    121126        return new File(getPreferencesDirFile(), "plugins");
     
    253258                properties.put(key, value);
    254259            }
    255             save();
     260            try {
     261                save();
     262            } catch(IOException e){
     263                System.out.println(tr("Warning: failed to persist preferences to ''{0}''", getPreferenceFile().getAbsoluteFile()));
     264            }
    256265            firePreferenceChanged(key, value);
    257266            return true;
     
    286295     * in log.
    287296     */
    288     public void save() {
     297    public void save() throws IOException {
    289298        /* currently unused, but may help to fix configuration issues in future */
    290299        properties.put("josm.version", AboutAction.getVersionString());
     300
     301        setSystemProperties();
     302        File prefFile = new File(getPreferencesDirFile(), "preferences");
     303
     304        // Backup old preferences if there are old preferences
     305        if(prefFile.exists()) {
     306            copyFile(prefFile, new File(prefFile + "_backup"));
     307        }
     308
     309        final PrintWriter out = new PrintWriter(new OutputStreamWriter(
     310                new FileOutputStream(prefFile + "_tmp"), "utf-8"), false);
     311        for (final Entry<String, String> e : properties.entrySet()) {
     312            String s = defaults.get(e.getKey());
     313            /* don't save default values */
     314            if(s == null || !s.equals(e.getValue())) {
     315                out.println(e.getKey() + "=" + e.getValue());
     316            }
     317        }
     318        out.close();
     319
     320        File tmpFile = new File(prefFile + "_tmp");
     321        copyFile(tmpFile, prefFile);
     322        tmpFile.delete();
     323    }
     324
     325    /**
     326     * Simple file copy function that will overwrite the target file
     327     * Taken from http://www.rgagnon.com/javadetails/java-0064.html (CC-NC-BY-SA)
     328     * @param in
     329     * @param out
     330     * @throws IOException
     331     */
     332    public static void copyFile(File in, File out) throws IOException  {
     333        FileChannel inChannel = new FileInputStream(in).getChannel();
     334        FileChannel outChannel = new FileOutputStream(out).getChannel();
    291335        try {
    292             setSystemProperties();
    293             final PrintWriter out = new PrintWriter(new OutputStreamWriter(
    294                     new FileOutputStream(getPreferencesDir() + "preferences"), "utf-8"), false);
    295             for (final Entry<String, String> e : properties.entrySet()) {
    296                 String s = defaults.get(e.getKey());
    297                 /* don't save default values */
    298                 if(s == null || !s.equals(e.getValue())) {
    299                     out.println(e.getKey() + "=" + e.getValue());
    300                 }
    301             }
    302             out.close();
    303         } catch (final IOException e) {
    304             e.printStackTrace();
    305             // do not message anything, since this can be called from strange
    306             // places.
    307         }
    308     }
     336            inChannel.transferTo(0, inChannel.size(),
     337                    outChannel);
     338        }
     339        catch (IOException e) {
     340            throw e;
     341        }
     342        finally {
     343            if (inChannel != null) {
     344                inChannel.close();
     345            }
     346            if (outChannel != null) {
     347                outChannel.close();
     348            }
     349        }
     350    }
     351
    309352
    310353    public void load() throws IOException {
     
    327370    }
    328371
    329     public void init(Boolean reset)
    330     {
     372    public void init(boolean reset){
    331373        // get the preferences.
    332374        File prefDir = getPreferencesDirFile();
    333375        if (prefDir.exists()) {
    334376            if(!prefDir.isDirectory()) {
     377                System.err.println(tr("Warning: Failed to initialize preferences. Preference directory ''{0}'' isn't a directory.", prefDir.getAbsoluteFile()));
    335378                JOptionPane.showMessageDialog(
    336379                        Main.parent,
    337                         tr("Cannot open preferences directory: {0}",Main.pref.getPreferencesDir()),
     380                        tr("<html>Failed to initialize preferences.<br>Preference directory ''{0}'' isn't a directory.</html>", prefDir.getAbsoluteFile()),
    338381                        tr("Error"),
    339382                        JOptionPane.ERROR_MESSAGE
     
    342385            }
    343386        } else {
    344             prefDir.mkdirs();
    345         }
    346 
    347         if (!new File(getPreferencesDir()+"preferences").exists()) {
    348             resetToDefault();
    349         }
    350 
     387            if (! prefDir.mkdirs()) {
     388                System.err.println(tr("Warning: Failed to initialize preferences. Failed to create missing preference directory: {0}", prefDir.getAbsoluteFile()));
     389                JOptionPane.showMessageDialog(
     390                        Main.parent,
     391                        tr("<html>Failed to initialize preferences.<br>Failed to create missing preference directory: {0}</html>",prefDir.getAbsoluteFile()),
     392                        tr("Error"),
     393                        JOptionPane.ERROR_MESSAGE
     394                );
     395                return;
     396            }
     397        }
     398
     399        File preferenceFile = getPreferenceFile();
    351400        try {
    352             if (reset) {
     401            if (!preferenceFile.exists()) {
     402                System.out.println(tr("Warning: Missing preference file ''{0}''. Creating a default preference file.", preferenceFile.getAbsoluteFile()));
    353403                resetToDefault();
    354             } else {
    355                 load();
    356             }
    357         } catch (final IOException e1) {
    358             e1.printStackTrace();
    359             String backup = getPreferencesDir() + "preferences.bak";
     404                save();
     405            } else if (reset) {
     406                System.out.println(tr("Warning: Replacing existing preference file ''{0}'' with default preference file.", preferenceFile.getAbsoluteFile()));
     407                resetToDefault();
     408                save();
     409            }
     410        } catch(IOException e) {
     411            e.printStackTrace();
    360412            JOptionPane.showMessageDialog(
    361413                    Main.parent,
    362                     tr("Preferences file had errors. Making backup of old one to {0}.", backup),
     414                    tr("<html>Failed to initialize preferences.<br>Failed to reset preference file to default: {0}</html>",getPreferenceFile().getAbsoluteFile()),
    363415                    tr("Error"),
    364416                    JOptionPane.ERROR_MESSAGE
    365417            );
    366             new File(getPreferencesDir() + "preferences").renameTo(new File(backup));
    367             save();
    368         }
    369     }
    370 
    371     public final void resetToDefault() {
     418            return;
     419        }
     420        try {
     421            load();
     422        } catch (IOException e) {
     423            e.printStackTrace();
     424            File backupFile = new File(prefDir,"preferences.bak");
     425            JOptionPane.showMessageDialog(
     426                    Main.parent,
     427                    tr("<html>Preferences file had errors.<br> Making backup of old one to <br>{0}<br> and creating a new default preference file.</html>", backupFile.getAbsoluteFile()),
     428                    tr("Error"),
     429                    JOptionPane.ERROR_MESSAGE
     430            );
     431            preferenceFile.renameTo(backupFile);
     432            try {
     433                resetToDefault();
     434                save();
     435            } catch(IOException e1) {
     436                e1.printStackTrace();
     437                System.err.println(tr("Warning: Failed to initialize preferences.Failed to reset preference file to default: {0}", getPreferenceFile()));
     438            }
     439        }
     440    }
     441
     442    public final void resetToDefault(){
    372443        properties.clear();
    373444        put("layerlist.visible", true);
     
    380451            put("laf", "com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    381452        }
    382         save();
     453    }
     454
     455    public File getBookmarksFile() {
     456        return new File(getPreferencesDir(),"bookmarks");
    383457    }
    384458
    385459    public Collection<Bookmark> loadBookmarks() throws IOException {
    386         File bookmarkFile = new File(getPreferencesDir()+"bookmarks");
     460        File bookmarkFile = getBookmarksFile();
    387461        if (!bookmarkFile.exists()) {
    388462            bookmarkFile.createNewFile();
  • /trunk/src/org/openstreetmap/josm/data/UndoRedoHandler.java

    r2024 r2060  
    4242        if (Main.map != null && Main.map.mapView.getActiveLayer() instanceof OsmDataLayer) {
    4343            OsmDataLayer data = (OsmDataLayer)Main.map.mapView.getActiveLayer();
    44             data.setModified(true);
    4544            data.fireDataChange();
    4645        }
     
    6261        if (Main.map != null && Main.map.mapView.getActiveLayer() instanceof OsmDataLayer) {
    6362            OsmDataLayer data = (OsmDataLayer)Main.map.mapView.getActiveLayer();
    64             data.setModified(data.uploadedModified || !commands.isEmpty());
    6563            data.fireDataChange();
    6664        }
     
    8179        if (Main.map != null && Main.map.mapView.getActiveLayer() instanceof OsmDataLayer) {
    8280            OsmDataLayer data = (OsmDataLayer)Main.map.mapView.getActiveLayer();
    83             data.setModified(true);
    8481            data.fireDataChange();
    8582        }
  • /trunk/src/org/openstreetmap/josm/data/osm/DataSet.java

    r2024 r2060  
    8383        Collection<OsmPrimitive> o = new LinkedList<OsmPrimitive>();
    8484        for (OsmPrimitive osm : allPrimitives())
    85             if (osm.visible && !osm.deleted) {
     85            if (osm.isVisible() && !osm.isDeleted()) {
    8686                o.add(osm);
    8787            }
     
    9292        Collection<OsmPrimitive> o = new LinkedList<OsmPrimitive>();
    9393        for (OsmPrimitive osm : allPrimitives())
    94             if (osm.visible && !osm.deleted && !osm.incomplete) {
     94            if (osm.isVisible() && !osm.isDeleted() && !osm.incomplete) {
    9595                o.add(osm);
    9696            }
     
    101101        Collection<OsmPrimitive> o = new LinkedList<OsmPrimitive>();
    102102        for (OsmPrimitive osm : allPrimitives())
    103             if (osm.visible && !osm.deleted && !osm.incomplete && !(osm instanceof Relation)) {
     103            if (osm.isVisible() && !osm.isDeleted() && !osm.incomplete && !(osm instanceof Relation)) {
    104104                o.add(osm);
    105105            }
     
    230230            return sel;
    231231        for (OsmPrimitive osm : list)
    232             if (osm.isSelected() && !osm.deleted) {
     232            if (osm.isSelected() && !osm.isDeleted()) {
    233233                sel.add(osm);
    234234            }
     
    290290                    String as = h.get(a);
    291291                    if (as == null) {
    292                         as = a.getName() != null ? a.getName() : Long.toString(a.id);
     292                        as = a.getName() != null ? a.getName() : Long.toString(a.getId());
    293293                        h.put(a, as);
    294294                    }
    295295                    String bs = h.get(b);
    296296                    if (bs == null) {
    297                         bs = b.getName() != null ? b.getName() : Long.toString(b.id);
     297                        bs = b.getName() != null ? b.getName() : Long.toString(b.getId());
    298298                        h.put(b, bs);
    299299                    }
     
    320320            throw new IllegalArgumentException(tr("parameter {0} > 0 required. Got {1}.", "id", id));
    321321        for (OsmPrimitive primitive : nodes) {
    322             if (primitive.id == id) return primitive;
     322            if (primitive.getId() == id) return primitive;
    323323        }
    324324        for (OsmPrimitive primitive : ways) {
    325             if (primitive.id == id) return primitive;
     325            if (primitive.getId() == id) return primitive;
    326326        }
    327327        for (OsmPrimitive primitive : relations) {
    328             if (primitive.id == id) return primitive;
     328            if (primitive.getId() == id) return primitive;
    329329        }
    330330        return null;
     
    334334        HashSet<Long> ret = new HashSet<Long>();
    335335        for (OsmPrimitive primitive : nodes) {
    336             ret.add(primitive.id);
     336            ret.add(primitive.getId());
    337337        }
    338338        for (OsmPrimitive primitive : ways) {
    339             ret.add(primitive.id);
     339            ret.add(primitive.getId());
    340340        }
    341341        for (OsmPrimitive primitive : relations) {
    342             ret.add(primitive.id);
     342            ret.add(primitive.getId());
    343343        }
    344344        return ret;
     
    346346
    347347    /**
    348      * Replies the set of ids of all complete primitivies (i.e. those with
     348     * Replies the set of ids of all complete primitives (i.e. those with
    349349     * ! primitive.incomplete)
    350350     *
    351      * @return the set of ids of all complete primitivies
     351     * @return the set of ids of all complete primitives
    352352     */
    353353    public Set<Long> getCompletePrimitiveIds() {
     
    355355        for (OsmPrimitive primitive : nodes) {
    356356            if (!primitive.incomplete) {
    357                 ret.add(primitive.id);
     357                ret.add(primitive.getId());
    358358            }
    359359        }
    360360        for (OsmPrimitive primitive : ways) {
    361361            if (! primitive.incomplete) {
    362                 ret.add(primitive.id);
     362                ret.add(primitive.getId());
    363363            }
    364364        }
    365365        for (OsmPrimitive primitive : relations) {
    366366            if (! primitive.incomplete) {
    367                 ret.add(primitive.id);
     367                ret.add(primitive.getId());
    368368            }
    369369        }
     
    451451        return parents;
    452452    }
     453
     454    /**
     455     * Replies true if there is at least one primitive in this dataset with
     456     * {@see OsmPrimitive#isModified()} == <code>true</code>.
     457     *
     458     * @return true if there is at least one primitive in this dataset with
     459     * {@see OsmPrimitive#isModified()} == <code>true</code>.
     460     */
     461    public boolean isModified() {
     462        for (Node n: nodes) {
     463            if (n.isModified()) return true;
     464        }
     465        for (Way w: ways) {
     466            if (w.isModified()) return true;
     467        }
     468        for (Relation r: relations) {
     469            if (r.isModified()) return true;
     470        }
     471        return false;
     472    }
    453473}
  • /trunk/src/org/openstreetmap/josm/data/osm/OsmPrimitive.java

    r2024 r2060  
    6969     * new to the server! To create a new object, call the default constructor of
    7070     * the respective class.
    71      */
     71     *
     72     * @deprecated use {@see #getId()}. Don't assign an id, create a primitive with
     73     * the respective constructors.
     74     */
     75    @Deprecated
    7276    public long id = 0;
    7377
     
    7781     * Deleted objects are deleted from the server. If the objects are added (id=0),
    7882     * the modified is ignored and the object is added to the server.
    79      */
     83     *
     84     * @deprecated Please use {@see #setModified()} and {@see #getModified()}
     85     */
     86    @Deprecated
    8087    public boolean modified = false;
    8188
    8289    /**
    8390     * <code>true</code>, if the object has been deleted.
    84      */
     91     *
     92     * @deprecated use {@see #delete()} and {@see #isDeleted()}
     93     */
     94    @Deprecated
    8595    public boolean deleted = false;
    8696
     
    8999     * introduced with the 0.4 API to be able to communicate deleted objects
    90100     * (they will have visible=false).
    91      */
     101     *
     102     * @deprecated use {@see #isVisible()} and {@see #setVisible(boolean)}
     103     */
     104    @Deprecated
    92105    public boolean visible = true;
    93106
     
    100113    /**
    101114     * If set to true, this object is currently selected.
     115     *
     116     * @deprecated use {@see #isSelected()} and {@see #setSelected(boolean)}
    102117     */
    103118    @Deprecated
     
    121136    public boolean isSelected() {
    122137        return selected;
     138    }
     139
     140    /**
     141     * Marks this primitive as being modified.
     142     *
     143     * @param modified true, if this primitive is to be modified
     144     */
     145    public void setModified(boolean modified) {
     146        this.modified = modified;
     147    }
     148
     149    /**
     150     * Replies <code>true</code> if the object has been modified since it was loaded from
     151     * the server. In this case, on next upload, this object will be updated.
     152     *
     153     * @return <code>true</code> if the object has been modified since it was loaded from
     154     * the server
     155     */
     156    public boolean isModified() {
     157        return modified;
     158    }
     159
     160    /**
     161     * Replies <code>true</code>, if the object has been deleted.
     162     *
     163     * @return <code>true</code>, if the object has been deleted.
     164     * @see #delete(boolean)
     165     */
     166    public boolean isDeleted() {
     167        return deleted;
     168    }
     169
     170    /**
     171     * Replies true if this primitive is either unknown to the server (i.e. its id
     172     * is 0) or it is known to the server and it hasn't be deleted on the server.
     173     * Replies false, if this primitive is known on the server and has been deleted
     174     * on the server.
     175     *
     176     * @see #setVisible(boolean)
     177     */
     178    public boolean isVisible() {
     179        return visible;
     180    }
     181
     182    /**
     183     * Sets whether this primitive is visible, i.e. whether it is known on the server
     184     * and not deleted on the server.
     185     *
     186     * @see #isVisible()
     187     * @throws IllegalStateException thrown if visible is set to false on an primitive with
     188     * id==0
     189     */
     190    public void setVisible(boolean visible) throws IllegalStateException{
     191        if (id == 0 && visible == false)
     192            throw new IllegalStateException(tr("a primitive with id=0 can't be invisible"));
     193        this.visible = visible;
     194    }
     195
     196    /**
     197     * Replies the id of this primitive.
     198     *
     199     * @return the id of this primitive.
     200     */
     201    public long getId() {
     202        return id;
    123203    }
    124204
     
    502582     */
    503583    public abstract String getDisplayName(NameFormatter formatter);
     584
    504585}
     586
     587
  • /trunk/src/org/openstreetmap/josm/data/osm/User.java

    r2024 r2060  
    3939        return user;
    4040    }
     41
     42    @Override
     43    public int hashCode() {
     44        final int prime = 31;
     45        int result = 1;
     46        result = prime * result + ((name == null) ? 0 : name.hashCode());
     47        result = prime * result + ((uid == null) ? 0 : uid.hashCode());
     48        return result;
     49    }
     50
     51    @Override
     52    public boolean equals(Object obj) {
     53        if (this == obj)
     54            return true;
     55        if (obj == null)
     56            return false;
     57        if (getClass() != obj.getClass())
     58            return false;
     59        User other = (User) obj;
     60        if (name == null) {
     61            if (other.name != null)
     62                return false;
     63        } else if (!name.equals(other.name))
     64            return false;
     65        if (uid == null) {
     66            if (other.uid != null)
     67                return false;
     68        } else if (!uid.equals(other.uid))
     69            return false;
     70        return true;
     71    }
    4172}
  • /trunk/src/org/openstreetmap/josm/data/osm/visitor/CreateOsmChangeVisitor.java

    r2024 r2060  
    4747
    4848    public void visit(Node n) {
    49         if (n.deleted) {
     49        if (n.isDeleted()) {
    5050            switchMode("delete");
    5151            osmwriter.setWithBody(false);
    5252            osmwriter.visit(n);
    5353        } else {
    54             switchMode((n.id == 0) ? "create" : "modify");
     54            switchMode((n.getId() == 0) ? "create" : "modify");
    5555            osmwriter.setWithBody(true);
    5656            osmwriter.visit(n);
     
    5858    }
    5959    public void visit(Way w) {
    60         if (w.deleted) {
     60        if (w.isDeleted()) {
    6161            switchMode("delete");
    6262            osmwriter.setWithBody(false);
    6363            osmwriter.visit(w);
    6464        } else {
    65             switchMode((w.id == 0) ? "create" : "modify");
     65            switchMode((w.getId() == 0) ? "create" : "modify");
    6666            osmwriter.setWithBody(true);
    6767            osmwriter.visit(w);
     
    6969    }
    7070    public void visit(Relation r) {
    71         if (r.deleted) {
     71        if (r.isDeleted()) {
    7272            switchMode("delete");
    7373            osmwriter.setWithBody(false);
    7474            osmwriter.visit(r);
    7575        } else {
    76             switchMode((r.id == 0) ? "create" : "modify");
     76            switchMode((r.getId() == 0) ? "create" : "modify");
    7777            osmwriter.setWithBody(true);
    7878            osmwriter.visit(r);
  • /trunk/src/org/openstreetmap/josm/data/osm/visitor/MapPaintVisitor.java

    r2024 r2060  
    529529            for (RelationMember m : r.getMembers())
    530530            {
    531                 if (m.isNode() && !m.getMember().incomplete && !m.getMember().deleted)
     531                if (m.isNode() && !m.getMember().incomplete && !m.getMember().isDeleted())
    532532                {
    533533                    drawSelectedMember(m.getMember(), styles != null ? getPrimitiveStyle(m.getMember()) : null, true, true);
     
    550550            for (RelationMember m : r.getMembers())
    551551            {
    552                 if (m.isWay() && !m.getMember().incomplete && !m.getMember().deleted) /* nodes drawn on second call */
     552                if (m.isWay() && !m.getMember().incomplete && !m.getMember().isDeleted()) /* nodes drawn on second call */
    553553                {
    554554                    drawSelectedMember(m.getMember(), styles != null ? getPrimitiveStyle(m.getMember())
     
    580580                // TODO Nullable member will not be allowed after RelationMember.member is encalupsed
    581581                r.putError(tr("Empty member in relation."), true);
    582             } else if(m.getMember().deleted) {
     582            } else if(m.getMember().isDeleted()) {
    583583                r.putError(tr("Deleted member ''{0}'' in relation.",
    584584                        m.getMember().getDisplayName(DefaultNameFormatter.getInstance())), true);
     
    834834                //TODO Remove useless nullcheck when RelationMember.member is encalupsed
    835835                r.putError(tr("Empty member in relation."), true);
    836             } else if(m.getMember().deleted) {
     836            } else if(m.getMember().isDeleted()) {
    837837                r.putError(tr("Deleted member ''{0}'' in relation.",
    838838                        m.getMember().getDisplayName(DefaultNameFormatter.getInstance())), true);
     
    13791379            for (final Relation osm : data.relations)
    13801380            {
    1381                 if(!osm.deleted && !osm.incomplete && osm.mappaintVisibleCode != viewid)
     1381                if(!osm.isDeleted() && !osm.incomplete && osm.mappaintVisibleCode != viewid)
    13821382                {
    13831383                    osm.visit(this);
     
    13961396            for (final Way osm : data.ways)
    13971397            {
    1398                 if (!osm.incomplete && !osm.deleted
     1398                if (!osm.incomplete && !osm.isDeleted()
    13991399                        && osm.mappaintVisibleCode != viewid && osm.mappaintDrawnCode != paintid)
    14001400                {
     
    14371437            //    profilerN = 0;
    14381438            for (final OsmPrimitive osm : data.ways)
    1439                 if (!osm.incomplete && !osm.deleted && !osm.isSelected()
     1439                if (!osm.incomplete && !osm.isDeleted() && !osm.isSelected()
    14401440                        && osm.mappaintVisibleCode != viewid )
    14411441                {
     
    14561456        //profilerN = 0;
    14571457        for (final OsmPrimitive osm : data.getSelected()) {
    1458             if (!osm.incomplete && !osm.deleted && !(osm instanceof Node)
     1458            if (!osm.incomplete && !osm.isDeleted() && !(osm instanceof Node)
    14591459                    && osm.mappaintVisibleCode != viewid && osm.mappaintDrawnCode != paintid)
    14601460            {
     
    14761476        //profilerN = 0;
    14771477        for (final OsmPrimitive osm : data.nodes)
    1478             if (!osm.incomplete && !osm.deleted
     1478            if (!osm.incomplete && !osm.isDeleted()
    14791479                    && osm.mappaintVisibleCode != viewid && osm.mappaintDrawnCode != paintid)
    14801480            {
     
    14961496            currentColor = nodeColor;
    14971497            for (final OsmPrimitive osm : data.ways)
    1498                 if (!osm.incomplete && !osm.deleted
     1498                if (!osm.incomplete && !osm.isDeleted()
    14991499                        && osm.mappaintVisibleCode != viewid )
    15001500                {
  • /trunk/src/org/openstreetmap/josm/data/osm/visitor/MergeSourceBuildingVisitor.java

    r2024 r2060  
    9494        for (RelationMember member: r.getMembers()) {
    9595            newMembers.add(
    96                 new RelationMember(member.getRole(), mappedPrimitives.get(member.getMember())));
     96                    new RelationMember(member.getRole(), mappedPrimitives.get(member.getMember())));
    9797
    9898        }
     
    117117        OsmPrimitive clone = null;
    118118        if (primitive instanceof Node) {
    119             clone = new Node(primitive.id);
     119            clone = new Node(primitive.getId());
    120120        } else if (primitive instanceof Way) {
    121             clone = new Way(primitive.id);
     121            clone = new Way(primitive.getId());
    122122        } else if (primitive instanceof Relation) {
    123             clone = new Relation(primitive.id);
     123            clone = new Relation(primitive.getId());
    124124        }
    125125        clone.incomplete = true;
     
    176176
    177177    protected boolean isNew(OsmPrimitive primitive) {
    178         return primitive.id == 0;
     178        return primitive.getId() == 0;
    179179    }
    180180
  • /trunk/src/org/openstreetmap/josm/data/osm/visitor/MergeVisitor.java

    r2024 r2060  
    6262        this.theirDataSet = theirDataSet;
    6363
    64         for (Node n : myDataSet.nodes) if (n.id != 0) {
    65             nodeshash.put(n.id, n);
    66         }
    67         for (Way w : myDataSet.ways) if (w.id != 0) {
    68             wayshash.put(w.id, w);
    69         }
    70         for (Relation r : myDataSet.relations) if (r.id != 0) {
    71             relshash.put(r.id, r);
     64        for (Node n : myDataSet.nodes) if (n.getId() != 0) {
     65            nodeshash.put(n.getId(), n);
     66        }
     67        for (Way w : myDataSet.ways) if (w.getId() != 0) {
     68            wayshash.put(w.getId(), w);
     69        }
     70        for (Relation r : myDataSet.relations) if (r.getId() != 0) {
     71            relshash.put(r.getId(), r);
    7272        }
    7373        conflicts = new ConflictCollection();
     
    9898            HashMap<Long, P> primitivesWithDefinedIds) {
    9999
    100         if (other.id > 0 ) {
     100        if (other.getId() > 0 ) {
    101101            // try to merge onto a matching primitive with the same
    102102            // defined id
     
    109109            //
    110110            for (P my : myPrimitives) {
    111                 if (my.id >0 ) {
     111                if (my.getId() >0 ) {
    112112                    continue;
    113113                }
    114114                if (my.hasEqualSemanticAttributes(other)) {
    115                     if (my.deleted != other.deleted) {
     115                    if (my.isDeleted() != other.isDeleted()) {
    116116                        // differences in deleted state have to be merged manually
    117117                        //
     
    120120                        // copy the technical attributes from other
    121121                        // version
    122                         my.visible = other.visible;
     122                        my.setVisible(other.isVisible());
    123123                        my.user = other.user;
    124124                        my.setTimestamp(other.getTimestamp());
    125                         my.modified = other.modified;
     125                        my.setModified(other.isModified());
    126126                        merged.put(other, my);
    127127                    }
     
    186186            Node mergedNode = (Node) merged.get(myNode);
    187187            if (mergedNode != null) {
    188                 if (!mergedNode.deleted) {
     188                if (!mergedNode.isDeleted()) {
    189189                    newNodes.add(mergedNode);
    190190                }
     
    207207                newMembers.add(myMember);
    208208            } else {
    209                 if (! mergedMember.deleted) {
     209                if (! mergedMember.isDeleted()) {
    210210                    RelationMember newMember = new RelationMember(myMember.getRole(), mergedMember);
    211211                    newMembers.add(newMember);
     
    234234        // merge other into an existing primitive with the same id, if possible
    235235        //
    236         if (myPrimitivesWithDefinedIds.containsKey(other.id)) {
    237             P my = myPrimitivesWithDefinedIds.get(other.id);
     236        if (myPrimitivesWithDefinedIds.containsKey(other.getId())) {
     237            P my = myPrimitivesWithDefinedIds.get(other.getId());
    238238            if (my.version <= other.version) {
    239                 if (! my.visible && other.visible) {
     239                if (! my.isVisible() && other.isVisible()) {
    240240                    // should not happen
    241241                    //
     
    243243                            + "their primitive with lower version {2} is not visible. "
    244244                            + "Can't deal with this inconsistency. Keeping my primitive. ",
    245                             Long.toString(my.id),Long.toString(my.version), Long.toString(other.version)
     245                            Long.toString(my.getId()),Long.toString(my.version), Long.toString(other.version)
    246246                    ));
    247247                    merged.put(other, my);
    248                 } else if (my.visible && ! other.visible) {
     248                } else if (my.isVisible() && ! other.isVisible()) {
    249249                    // this is always a conflict because the user has to decide whether
    250250                    // he wants to create a clone of its local primitive or whether he
     
    270270                    //
    271271                    merged.put(other, my);
    272                 } else if (my.deleted && ! other.deleted && my.version == other.version) {
     272                } else if (my.isDeleted() && ! other.isDeleted() && my.version == other.version) {
    273273                    // same version, but my is deleted. Assume mine takes precedence
    274274                    // otherwise too many conflicts when refreshing from the server
    275275                    merged.put(other, my);
    276                 } else if (my.deleted != other.deleted) {
     276                } else if (my.isDeleted() != other.isDeleted()) {
    277277                    // differences in deleted state have to be resolved manually
    278278                    //
    279279                    conflicts.add(my,other);
    280                 } else if (! my.modified && other.modified) {
     280                } else if (! my.isModified() && other.isModified()) {
    281281                    // my not modified. We can assume that other is the most recent version.
    282282                    // clone it onto my. But check first, whether other is deleted. if so,
    283283                    // make sure that my is not references anymore in myDataSet.
    284284                    //
    285                     if (other.deleted) {
     285                    if (other.isDeleted()) {
    286286                        myDataSet.unlinkReferencesToPrimitive(my);
    287287                    }
    288288                    my.cloneFrom(other);
    289289                    merged.put(other, my);
    290                 } else if (! my.modified && !other.modified && my.version == other.version) {
     290                } else if (! my.isModified() && !other.isModified() && my.version == other.version) {
    291291                    // both not modified. Keep mine
    292292                    //
    293293                    merged.put(other,my);
    294                 } else if (! my.modified && !other.modified && my.version < other.version) {
     294                } else if (! my.isModified() && !other.isModified() && my.version < other.version) {
    295295                    // my not modified but other is newer. clone other onto mine.
    296296                    //
    297297                    my.cloneFrom(other);
    298298                    merged.put(other,my);
    299                 } else if (my.modified && ! other.modified && my.version == other.version) {
     299                } else if (my.isModified() && ! other.isModified() && my.version == other.version) {
    300300                    // my is same as other but mine is modified
    301301                    // => keep mine
     
    312312                    //
    313313                    my.cloneFrom(other);
    314                     my.modified = true;
     314                    my.setModified(true);
    315315                    merged.put(other, my);
    316316                }
  • /trunk/src/org/openstreetmap/josm/data/osm/visitor/SimplePaintVisitor.java

    r2024 r2060  
    5656    /**
    5757     * Preferences
    58     */
     58     */
    5959    protected Color inactiveColor;
    6060    protected Color selectedColor;
     
    124124
    125125        ((Graphics2D)g).setRenderingHint(RenderingHints.KEY_ANTIALIASING,
    126             Main.pref.getBoolean("mappaint.use-antialiasing", false) ?
    127             RenderingHints.VALUE_ANTIALIAS_ON : RenderingHints.VALUE_ANTIALIAS_OFF);
     126                Main.pref.getBoolean("mappaint.use-antialiasing", false) ?
     127                        RenderingHints.VALUE_ANTIALIAS_ON : RenderingHints.VALUE_ANTIALIAS_OFF);
    128128    }
    129129
     
    149149        //profilerN = 0;
    150150        for (final OsmPrimitive osm : data.relations)
    151             if (!osm.deleted && !osm.isSelected())
     151            if (!osm.isDeleted() && !osm.isSelected())
    152152            {
    153153                osm.visit(this);
    154         //        profilerN++;
     154                //        profilerN++;
    155155            }
    156156
     
    163163        //profilerN = 0;
    164164        for (final OsmPrimitive osm : data.ways)
    165             if (!osm.deleted && !osm.isSelected() && osm.isTagged())
     165            if (!osm.isDeleted() && !osm.isSelected() && osm.isTagged())
    166166            {
    167167                osm.visit(this);
    168         //        profilerN++;
     168                //        profilerN++;
    169169            }
    170170        displaySegments();
    171171
    172172        for (final OsmPrimitive osm : data.ways)
    173             if (!osm.deleted && !osm.isSelected() && !osm.isTagged())
     173            if (!osm.isDeleted() && !osm.isSelected() && !osm.isTagged())
    174174            {
    175175                osm.visit(this);
    176         //        profilerN++;
     176                //        profilerN++;
    177177            }
    178178        displaySegments();
     
    187187        //profilerN = 0;
    188188        for (final OsmPrimitive osm : data.getSelected())
    189             if (!osm.deleted)
     189            if (!osm.isDeleted())
    190190            {
    191191                osm.visit(this);
    192         //        profilerN++;
     192                //        profilerN++;
    193193            }
    194194        displaySegments();
     
    202202        //profilerN = 0;
    203203        for (final OsmPrimitive osm : data.nodes)
    204             if (!osm.deleted && !osm.isSelected())
     204            if (!osm.isDeleted() && !osm.isSelected())
    205205            {
    206206                osm.visit(this);
    207         //        profilerN++;
     207                //        profilerN++;
    208208            }
    209209
     
    217217        if(virtualNodeSize != 0)
    218218        {
    219         //    profilerN = 0;
     219            //    profilerN = 0;
    220220            currentColor = nodeColor;
    221221            for (final OsmPrimitive osm : data.ways)
    222                 if (!osm.deleted)
    223                     {
    224                         visitVirtual((Way)osm);
    225         //                profilerN++;
    226                     }
     222                if (!osm.isDeleted())
     223                {
     224                    visitVirtual((Way)osm);
     225                    //                profilerN++;
     226                }
    227227            displaySegments();
    228228
    229         //    if(profiler)
    230         //    {
    231         //        System.out.format("Virtual  : %4dms, n=%5d\n", (java.lang.System.currentTimeMillis()-profilerLast), profilerN);
    232         //        profilerLast = java.lang.System.currentTimeMillis();
    233         //    }
     229            //    if(profiler)
     230            //    {
     231            //        System.out.format("Virtual  : %4dms, n=%5d\n", (java.lang.System.currentTimeMillis()-profilerLast), profilerN);
     232            //        profilerLast = java.lang.System.currentTimeMillis();
     233            //    }
    234234        }
    235235
     
    249249        if (n.incomplete) return;
    250250
    251         if (inactive)
     251        if (inactive) {
    252252            drawNode(n, inactiveColor, unselectedNodeSize, unselectedNodeRadius, fillUnselectedNode);
    253         else if (n.highlighted)
     253        } else if (n.highlighted) {
    254254            drawNode(n, highlightColor, selectedNodeSize, selectedNodeRadius, fillSelectedNode);
    255         else if (n.isSelected())
     255        } else if (n.isSelected()) {
    256256            drawNode(n, selectedColor, selectedNodeSize, selectedNodeRadius, fillSelectedNode);
    257         else if(n.isTagged())
     257        } else if(n.isTagged()) {
    258258            drawNode(n, nodeColor, taggedNodeSize, taggedNodeRadius, fillUnselectedNode);
    259         else
     259        } else {
    260260            drawNode(n, nodeColor, unselectedNodeSize, unselectedNodeRadius, fillUnselectedNode);
     261        }
    261262    }
    262263
    263264    public static Boolean isLargeSegment(Point p1, Point p2, int space)
    264265    {
    265         int xd = p1.x-p2.x; if(xd < 0) xd = -xd;
    266         int yd = p1.y-p2.y; if(yd < 0) yd = -yd;
     266        int xd = p1.x-p2.x; if(xd < 0) {
     267            xd = -xd;
     268        }
     269        int yd = p1.y-p2.y; if(yd < 0) {
     270            yd = -yd;
     271        }
    267272        return (xd+yd > space);
    268273    }
     
    325330                Point p = nc.getPoint(it.next());
    326331                drawSegment(lastP, p, wayColor,
    327                     showOnlyHeadArrowOnly ? !it.hasNext() : showThisDirectionArrow);
    328                 if (showOrderNumber)
     332                        showOnlyHeadArrowOnly ? !it.hasNext() : showThisDirectionArrow);
     333                if (showOrderNumber) {
    329334                    drawOrderNumber(lastP, p, orderNumber);
     335                }
    330336                lastP = p;
    331337            }
     
    334340
    335341    private Stroke relatedWayStroke = new BasicStroke(
    336         4, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_BEVEL);
     342            4, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_BEVEL);
    337343    public void visit(Relation r) {
    338344        if (r.incomplete) return;
     
    349355
    350356        for (RelationMember m : r.getMembers()) {
    351             if (m.getMember().incomplete || m.getMember().deleted) continue;
     357            if (m.getMember().incomplete || m.getMember().isDeleted()) {
     358                continue;
     359            }
    352360
    353361            if (m.isNode()) {
    354362                Point p = nc.getPoint(m.getNode());
    355363                if (p.x < 0 || p.y < 0
    356                     || p.x > nc.getWidth() || p.y > nc.getHeight()) continue;
     364                        || p.x > nc.getWidth() || p.y > nc.getHeight()) {
     365                    continue;
     366                }
    357367
    358368                g.drawOval(p.x-3, p.y-3, 6, 6);
     
    362372                boolean first = true;
    363373                for (Node n : m.getWay().getNodes()) {
    364                     if (n.incomplete || n.deleted) continue;
     374                    if (n.incomplete || n.isDeleted()) {
     375                        continue;
     376                    }
    365377                    Point p = nc.getPoint(n);
    366378                    if (first) {
     
    418430                g.fillRect(p.x - radius, p.y - radius, size, size);
    419431                g.drawRect(p.x - radius, p.y - radius, size, size);
    420             } else
     432            } else {
    421433                g.drawRect(p.x - radius, p.y - radius, size, size);
     434            }
    422435        }
    423436    }
     
    427440     */
    428441    protected void drawSegment(Point p1, Point p2, Color col, boolean showDirection) {
    429         if (col != currentColor) displaySegments(col);
     442        if (col != currentColor) {
     443            displaySegments(col);
     444        }
    430445
    431446        if (isSegmentVisible(p1, p2)) {
  • /trunk/src/org/openstreetmap/josm/gui/BookmarkList.java

    r2024 r2060  
    1414import org.openstreetmap.josm.Main;
    1515import org.openstreetmap.josm.data.Preferences;
     16
     17import sun.security.action.GetBooleanAction;
    1618
    1719/**
     
    4446            JOptionPane.showMessageDialog(
    4547                    Main.parent,
    46                     tr("<html>Could not read bookmarks.<br>{0}</html>", e.getMessage()),
     48                    tr("<html>Could not read bookmarks from<br>''{0}''<br>Error was: {1}</html>",
     49                            Main.pref.getBookmarksFile(),
     50                            e.getMessage()
     51                    ),
    4752                    tr("Error"),
    4853                    JOptionPane.ERROR_MESSAGE
  • /trunk/src/org/openstreetmap/josm/gui/ConditionalOptionPaneUtil.java

    r2024 r2060  
    2727 *
    2828 */
    29 public class ConditionalOptionPaneUtil {
     29@Deprecated public class ConditionalOptionPaneUtil {
    3030    static public final int DIALOG_DISABLED_OPTION = Integer.MIN_VALUE;
    3131
  • /trunk/src/org/openstreetmap/josm/gui/ExceptionDialogUtil.java

    r2024 r2060  
    1717import org.openstreetmap.josm.io.OsmApiException;
    1818import org.openstreetmap.josm.io.OsmApiInitializationException;
     19import org.openstreetmap.josm.io.OsmChangesetCloseException;
    1920import org.openstreetmap.josm.io.OsmTransferException;
    2021
     
    3940        JOptionPane.showMessageDialog(
    4041                Main.parent,
    41                 tr(   "Failed to initialize communication with the OSM server {0}.\n"
    42                         + "Check the server URL in your preferences and your internet connection.",
     42                tr(   "<html>Failed to initialize communication with the OSM server {0}.<br>"
     43                        + "Check the server URL in your preferences and your internet connection.</html>",
     44                        Main.pref.get("osm-server.url", "http://api.openstreetmap.org/api")
     45                ),
     46                tr("Error"),
     47                JOptionPane.ERROR_MESSAGE
     48        );
     49    }
     50
     51    /**
     52     * handles an exception caught during OSM API initialization
     53     *
     54     * @param e the exception
     55     */
     56    public static void explainOsmChangesetCloseException(OsmChangesetCloseException e) {
     57        e.printStackTrace();
     58        String changsetId = e.getChangeset() == null ? tr("unknown") : Long.toString(e.getChangeset().getId());
     59        JOptionPane.showMessageDialog(
     60                Main.parent,
     61                tr(   "<html>Failed to close changeset ''{0}'' on the OSM server ''{1}''.<br>"
     62                        + "The changeset will automatically be closed by the server after a timeout.</html>",
     63                        changsetId,
    4364                        Main.pref.get("osm-server.url", "http://api.openstreetmap.org/api")
    4465                ),
     
    275296            return;
    276297        }
     298        if (e instanceof OsmChangesetCloseException){
     299            explainOsmChangesetCloseException((OsmChangesetCloseException)e);
     300            return;
     301        }
     302
    277303        if (e instanceof OsmApiException) {
    278304            OsmApiException oae = (OsmApiException)e;
  • /trunk/src/org/openstreetmap/josm/gui/ExtendedDialog.java

    r2024 r2060  
    11package org.openstreetmap.josm.gui;
    22
     3import static org.openstreetmap.josm.tools.I18n.tr;
     4
    35import java.awt.Component;
     6import java.awt.Container;
    47import java.awt.Dimension;
     8import java.awt.Frame;
    59import java.awt.GridBagLayout;
    610import java.awt.Toolkit;
     
    1115import javax.swing.Action;
    1216import javax.swing.JButton;
     17import javax.swing.JCheckBox;
    1318import javax.swing.JComponent;
    1419import javax.swing.JDialog;
     
    1924import javax.swing.KeyStroke;
    2025
     26import org.openstreetmap.josm.Main;
    2127import org.openstreetmap.josm.tools.GBC;
    2228import org.openstreetmap.josm.tools.ImageProvider;
     
    2531public class ExtendedDialog extends JDialog {
    2632    private int result = 0;
     33    public static final int DialogNotShown = -99;
     34    public static final int DialogClosedOtherwise = 0;
     35    private boolean toggleable = false;
     36    private String togglePref = "";
     37    private String toggleCheckboxText = tr("Do not show again");
     38    private JCheckBox toggleCheckbox = null;
    2739    private Component parent;
     40    private Component content;
    2841    private final String[] bTexts;
     42    private String[] bIcons;
     43    /**
     44     * set to true if the content of the extended dialog should
     45     * be placed in a {@see JScrollPane}
     46     */
     47    private boolean placeContentInScrollPane;
    2948
    3049    // For easy access when inherited
    31     protected Object contentConstraints = GBC.eol().anchor(GBC.CENTER).fill(GBC.HORIZONTAL).insets(5,10,5,0);
     50    protected Object contentConstraints = GBC.eol().anchor(GBC.CENTER).fill(GBC.BOTH).insets(5,10,5,0);
    3251    protected ArrayList<JButton> buttons = new ArrayList<JButton>();
     52
     53    /**
     54     * This method sets up the most basic options for the dialog. Add all more
     55     * advanced features with dedicated methods.
     56     * Possible features:
     57     * <ul>
     58     *   <li><code>setButtonIcons</code></li>
     59     *   <li><code>setContent</code></li>
     60     *   <li><code>toggleEnable</code></li>
     61     *   <li><code>toggleDisable</code></li>
     62     *   <li><code>setToggleCheckboxText</code></li>
     63     * </ul>
     64     *
     65     * When done, call <code>showDialog</code> to display it. You can receive
     66     * the user's choice using <code>getValue</code>. Have a look at this function
     67     * for possible return values.
     68     *
     69     * @param parent       The parent element that will be used for position and maximum size
     70     * @param title        The text that will be shown in the window titlebar
     71     * @param buttonTexts  String Array of the text that will appear on the buttons. The first button is the default one.
     72     */
     73    public ExtendedDialog(Component parent, String title, String[] buttonTexts) {
     74        super(JOptionPane.getFrameForComponent(parent), title, true);
     75        this.parent = parent;
     76        bTexts = buttonTexts;
     77    }
     78
     79    /**
     80     * Same as above but lets you define if the dialog should be modal.
     81     */
     82    public ExtendedDialog(Component parent, String title, String[] buttonTexts,
     83            boolean modal) {
     84        super(JOptionPane.getFrameForComponent(parent), title, modal);
     85        this.parent = parent;
     86        bTexts = buttonTexts;
     87    }
    3388
    3489    /**
     
    4095     * @param buttonIcons The path to the icons that will be displayed on the buttons. Path is relative to JOSM's image directory. File extensions need to be included. If a button should not have an icon pass null.
    4196     */
    42     public ExtendedDialog(Component parent, String title, Component content, String[] buttonTexts, String[] buttonIcons) {
     97    @Deprecated public ExtendedDialog(Component parent, String title, Component content,
     98            String[] buttonTexts, String[] buttonIcons) {
    4399        super(JOptionPane.getFrameForComponent(parent), title, true /* modal */);
    44100        this.parent = parent;
    45101        bTexts = buttonTexts;
    46         setupDialog(content, buttonIcons);
     102        this.content = content;
     103        this.bIcons = buttonIcons;
     104        setupDialog();
    47105        setVisible(true);
    48106    }
    49107
    50     public ExtendedDialog(Component parent, String title, Component content, String[] buttonTexts) {
     108    @Deprecated public ExtendedDialog(Component parent, String title, Component content,
     109            String[] buttonTexts) {
    51110        this(parent, title, content, buttonTexts, null);
    52111    }
     
    55114     * Sets up the dialog and displays the given message in a breakable label
    56115     */
    57     public ExtendedDialog(Component parent, String title, String message, String[] buttonTexts, String[] buttonIcons) {
    58         super(JOptionPane.getFrameForComponent(parent), title, true);
    59 
    60         JMultilineLabel lbl = new JMultilineLabel(message);
    61         // Make it not wider than 2/3 of the screen
    62         Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
    63         lbl.setMaxWidth(Math.round(screenSize.width*2/3));
    64 
    65         this.parent = parent;
    66         bTexts = buttonTexts;
    67         setupDialog(lbl, buttonIcons);
     116    @Deprecated public ExtendedDialog(Component parent, String title, String message,
     117            String[] buttonTexts, String[] buttonIcons) {
     118        this(parent, title, string2label(message), buttonTexts, buttonIcons);
     119    }
     120
     121    @Deprecated public ExtendedDialog(Component parent, String title, String message,
     122            String[] buttonTexts) {
     123        this(parent, title, message, buttonTexts, null);
     124    }
     125
     126    /**
     127     * Allows decorating the buttons with icons. Expects an String[] with paths
     128     * to images relative to JOSM/images.
     129     * @param buttonIcons
     130     */
     131    public void setButtonIcons(String[] buttonIcons) {
     132        this.bIcons = buttonIcons;
     133    }
     134
     135    /**
     136     * Sets the content that will be displayed in the message dialog.
     137     *
     138     * Note that depending on your other settings more UI elements may appear.
     139     * The content is played on top of the other elements though.
     140     *
     141     * @param content Any element that can be displayed in the message dialog
     142     */
     143    public void setContent(Component content) {
     144        setContent(content, true);
     145    }
     146
     147    /**
     148     * Sets the content that will be displayed in the message dialog.
     149     *
     150     * Note that depending on your other settings more UI elements may appear.
     151     * The content is played on top of the other elements though.
     152     *
     153     * @param content Any element that can be displayed in the message dialog
     154     * @param placeContentInScrollPane if  true, places  the content in a JScrollPane
     155     *
     156     */
     157    public void setContent(Component content, boolean placeContentInScrollPane) {
     158        this.content = content;
     159        this.placeContentInScrollPane = placeContentInScrollPane;
     160    }
     161
     162    /**
     163     * Sets the message that will be displayed. The String will be automatically
     164     * wrapped if it is too long.
     165     *
     166     * Note that depending on your other settings more UI elements may appear.
     167     * The content is played on top of the other elements though.
     168     *
     169     * @param message The text that should be shown to the user
     170     */
     171    public void setContent(String message) {
     172        setContent(string2label(message), true);
     173    }
     174
     175    /**
     176     * Show the dialog to the user. Call this after you have set all options
     177     * for the dialog. You can retrieve the result using <code>getValue</code>
     178     */
     179    public void showDialog() {
     180        // Check if the user has set the dialog to not be shown again
     181        if(toggleCheckState(togglePref)) {
     182            result = ExtendedDialog.DialogNotShown;
     183            return;
     184        }
     185
     186        setupDialog();
    68187        setVisible(true);
    69     }
    70 
    71     public ExtendedDialog(Component parent, String title, String message, String[] buttonTexts) {
    72         this(parent, title, message, buttonTexts, null);
    73     }
    74 
    75     /**
    76      * Constructor that doesn't make the dialog visible immediately. Intended for when inheriting.
    77      */
    78     public ExtendedDialog(Component parent, String title, String[] buttonTexts, boolean modal) {
    79         super(JOptionPane.getFrameForComponent(parent), title, modal);
    80         this.parent = parent;
    81         bTexts = buttonTexts;
    82     }
    83 
    84     protected void setupDialog(Component content, String[] buttonIcons) {
     188        toggleSaveState();
     189    }
     190
     191    /**
     192     * @return int * The selected button. The count starts with 1.
     193     *             * A return value of ExtendedDialog.DialogClosedOtherwise means the dialog has been closed otherwise.
     194     *             * A return value of ExtendedDialog.DialogNotShown means the
     195     *               dialog has been toggled off in the past
     196     */
     197    public int getValue() {
     198        return result;
     199    }
     200
     201    @Deprecated protected void setupDialog(Component content, String[] buttonIcons) {
     202        this.setContent(content);
     203        this.setButtonIcons(buttonIcons);
     204        this.setupDialog();
     205    }
     206
     207    protected void setupDialog() {
    85208        setupEscListener();
    86209
     
    96219
    97220            button = new JButton(action);
    98             if(buttonIcons != null && buttonIcons[i] != null) {
    99                 button.setIcon(ImageProvider.get(buttonIcons[i]));
     221            if(bIcons != null && bIcons[i] != null) {
     222                button.setIcon(ImageProvider.get(bIcons[i]));
    100223            }
    101224
     
    109232        JPanel cp = new JPanel(new GridBagLayout());
    110233        cp.add(content, contentConstraints);
     234
     235        if(toggleable) {
     236            toggleCheckbox = new JCheckBox(toggleCheckboxText);
     237            boolean showDialog = Main.pref.getBoolean("message."+ togglePref, true);
     238            toggleCheckbox.setSelected(!showDialog);
     239            cp.add(toggleCheckbox, GBC.eol().anchor(GBC.LINE_START).insets(5,5,5,5));
     240        }
     241
    111242        cp.add(buttonsPanel, GBC.eol().anchor(GBC.CENTER).insets(5,5,5,5));
    112 
    113         JScrollPane pane = new JScrollPane(cp);
    114         pane.setBorder(null);
    115         setContentPane(pane);
    116 
     243        if (placeContentInScrollPane) {
     244            JScrollPane pane = new JScrollPane(cp);
     245            pane.setBorder(null);
     246            setContentPane(pane);
     247        } else {
     248            setContentPane(cp);
     249        }
    117250        pack();
    118251
     
    138271        setSize(d);
    139272        setLocationRelativeTo(parent);
    140     }
    141 
    142     /**
    143      * @return int The selected button. The count starts with 1.
    144      *             A return value of 0 means the dialog has been closed otherwise.
    145      */
    146     public int getValue() {
    147         return result;
    148273    }
    149274
     
    188313                // We need to set it to zero again, in case the dialog has been re-used
    189314                // and the result differs from its default value
    190                 result = 0;
     315                result = ExtendedDialog.DialogClosedOtherwise;
    191316                setVisible(false);
    192317            }
     
    202327        super.setVisible(visible);
    203328        if (visible) {
    204             toFront();
    205         }
     329            repaint();
     330        }
     331    }
     332
     333    /**
     334     * Calling this will offer the user a "Do not show again" checkbox for the
     335     * dialog. Default is to not offer the choice; the dialog will be shown
     336     * every time. If the dialog is not shown due to the previous choice of the
     337     * user, the result <code>ExtendedDialog.DialogNotShown</code> is returned
     338     * @param togglePref  The preference to save the checkbox state to
     339     */
     340    public void toggleEnable(String togglePref) {
     341        this.toggleable = true;
     342        this.togglePref = togglePref;
     343    }
     344
     345    /**
     346     * Call this if you "accidentally" called toggleEnable. This doesn't need
     347     * to be called for every dialog, as it's the default anyway.
     348     */
     349    public void toggleDisable() {
     350        this.toggleable = false;
     351    }
     352
     353    /**
     354     * Overwrites the default "Don't show again" text of the toggle checkbox
     355     * if you want to give more information. Only has an effect if
     356     * <code>toggleEnable</code> is set.
     357     * @param text
     358     */
     359    public void setToggleCheckboxText(String text) {
     360        this.toggleCheckboxText = text;
     361    }
     362
     363    /**
     364     * This function returns true if the dialog has been set to "do not show again"
     365     * @return true if dialog should not be shown again
     366     */
     367    private boolean toggleCheckState(String togglePref) {
     368        toggleable = togglePref != null && !togglePref.equals("");
     369
     370        // No identifier given, so return false (= show the dialog)
     371        if(!toggleable)
     372            return false;
     373
     374        this.togglePref = togglePref;
     375        // The pref is true, if the dialog should be shown.
     376        return !(Main.pref.getBoolean("message."+ togglePref, true));
     377    }
     378
     379    /**
     380     * This function checks the state of the "Do not show again" checkbox and
     381     * writes the corresponding pref
     382     */
     383    private void toggleSaveState() {
     384        if(!toggleable || toggleCheckbox == null)
     385            return;
     386        Main.pref.put("message."+ togglePref, !toggleCheckbox.isSelected());
     387    }
     388
     389    /**
     390     * Convenience function that converts a given string into a JMultilineLabel
     391     * @param msg
     392     * @return JMultilineLabel
     393     */
     394    private static JMultilineLabel string2label(String msg) {
     395        JMultilineLabel lbl = new JMultilineLabel(msg);
     396        // Make it not wider than 2/3 of the screen
     397        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
     398        lbl.setMaxWidth(Math.round(screenSize.width*2/3));
     399        return lbl;
    206400    }
    207401}
  • /trunk/src/org/openstreetmap/josm/gui/FileDrop.java

    r2024 r2060  
    99import java.io.PrintStream;
    1010import java.io.Reader;
    11 
     11import java.util.Arrays;
     12import java.util.List;
     13
     14import javax.swing.BorderFactory;
     15
     16import org.openstreetmap.josm.Main;
    1217import org.openstreetmap.josm.actions.OpenFileAction;
    1318
     
    6772
    6873    /* Constructor for JOSM file drop */
    69     public FileDrop(final java.awt.Component c)
    70     {   this(
    71             null,  // Logging stream
    72             c,     // Drop target
    73             javax.swing.BorderFactory.createMatteBorder( 2, 2, 2, 2, defaultBorderColor ), // Drag border
    74             true, // Recursive
    75             new FileDrop.Listener()
    76             {
    77                 public void filesDropped( java.io.File[] files )
    78                 {
    79                     OpenFileAction ofa = new OpenFileAction();
    80                     for( int i = 0; i < files.length; i++ )
    81                     {
    82                         ofa.openFile(files[i]);
    83                     }   // end for: through each dropped file
    84                 }   // end filesDropped
    85             }); // end FileDrop.Listener
     74    public FileDrop(final java.awt.Component c){
     75        this(
     76                null,  // Logging stream
     77                c,     // Drop target
     78                BorderFactory.createMatteBorder( 2, 2, 2, 2, defaultBorderColor ), // Drag border
     79                true, // Recursive
     80                new FileDrop.Listener(){
     81                    public void filesDropped( java.io.File[] files ){
     82                        // start asynchronous loading of files
     83                        OpenFileAction.OpenFileTask task = new OpenFileAction.OpenFileTask(Arrays.asList(files));
     84                        Main.worker.submit(task);
     85                    }
     86                }
     87        );
    8688    }
    87 
    8889
    8990    /**
     
    341342
    342343                    // Get a useful list
    343                     java.util.List fileList = (java.util.List)
     344                    List fileList = (java.util.List)
    344345                    tr.getTransferData(java.awt.datatransfer.DataFlavor.javaFileListFlavor);
    345346
    346347                    // Convert list to array
    347                     final java.io.File[] files = (File[]) fileList.toArray();;
     348                    final File[] files = (File[]) fileList.toArray();
    348349
    349350                    // Alert listener to drop.
  • /trunk/src/org/openstreetmap/josm/gui/MainApplet.java

    r2024 r2060  
    1010import java.awt.event.KeyEvent;
    1111import java.io.File;
     12import java.io.IOException;
    1213import java.net.URL;
    1314import java.util.Arrays;
     
    3637        public UploadPreferencesAction() {
    3738            super(tr("Upload Preferences"), "upload-preferences", tr("Upload the current preferences to the server"),
    38             Shortcut.registerShortcut("applet:uploadprefs", tr("Upload Preferences"), KeyEvent.VK_U, Shortcut.GROUP_HOTKEY), true);
     39                    Shortcut.registerShortcut("applet:uploadprefs", tr("Upload Preferences"), KeyEvent.VK_U, Shortcut.GROUP_HOTKEY), true);
    3940        }
    4041        public void actionPerformed(ActionEvent e) {
     
    7071        for (String[] s : paramInfo) {
    7172            Collection<String> p = readParameter(s[0], args.get(s[0]));
    72             if (p != null)
     73            if (p != null) {
    7374                args.put(s[0], p);
     75            }
    7476        }
    7577        if (!args.containsKey("geometry") && getParameter("width") != null && getParameter("height") != null) {
     
    98100        Main.pref = new ServerSidePreferences(getCodeBase());
    99101        ((ServerSidePreferences)Main.pref).download(username, password);
    100 
    101102        Main.preConstructorInit(args);
    102103        Main.parent = this;
     
    124125        String param = getParameter(s);
    125126        if (param != null) {
    126             if (v == null)
     127            if (v == null) {
    127128                v = new LinkedList<String>();
     129            }
    128130            v.addAll(Arrays.asList(param.split(";")));
    129131        }
  • /trunk/src/org/openstreetmap/josm/gui/MainApplication.java

    r2024 r2060  
    4747        mainFrame.addWindowListener(new WindowAdapter(){
    4848            @Override public void windowClosing(final WindowEvent arg0) {
    49                 if (Main.breakBecauseUnsavedChanges())
     49                if (!Main.saveUnsavedModifications())
    5050                    return;
    5151                Main.saveGuiGeometry();
     
    7373        final Map<String, Collection<String>> args = new HashMap<String, Collection<String>>();
    7474        for (String arg : argArray) {
    75             if (!arg.startsWith("--"))
     75            if (!arg.startsWith("--")) {
    7676                arg = "--download="+arg;
     77            }
    7778            int i = arg.indexOf('=');
    7879            String key = i == -1 ? arg.substring(2) : arg.substring(2,i);
    7980            String value = i == -1 ? "" : arg.substring(i+1);
    8081            Collection<String> v = args.get(key);
    81             if (v == null)
     82            if (v == null) {
    8283                v = new LinkedList<String>();
     84            }
    8385            v.add(value);
    8486            args.put(key, v);
     
    8890
    8991        // Check if passed as parameter
    90         if (args.containsKey("language"))
     92        if (args.containsKey("language")) {
    9193            I18n.set((String)(args.get("language").toArray()[0]));
    92         else
     94        } else {
    9395            I18n.set(Main.pref.get("language", null));
     96        }
    9497
    9598        if (argList.contains("--help") || argList.contains("-?") || argList.contains("-h")) {
     
    143146
    144147        if (((!args.containsKey("no-maximize") && !args.containsKey("geometry")
    145         && Main.pref.get("gui.geometry").length() == 0) || args.containsKey("maximize"))
    146         && Toolkit.getDefaultToolkit().isFrameStateSupported(JFrame.MAXIMIZED_BOTH))
     148                && Main.pref.get("gui.geometry").length() == 0) || args.containsKey("maximize"))
     149                && Toolkit.getDefaultToolkit().isFrameStateSupported(JFrame.MAXIMIZED_BOTH)) {
    147150            mainFrame.setExtendedState(JFrame.MAXIMIZED_BOTH);
     151        }
    148152
    149153        EventQueue.invokeLater(new Runnable() {
     
    161165    public static void removeObsoletePreferences() {
    162166        String[] obsolete = {
    163            "sample.preference.that.does.not.exist", // sample comment, expiry date should go here
    164            "osm-server.version", // remove this around 10/2009
    165            "osm-server.additional-versions", // remove this around 10/2009
    166            null
     167                "sample.preference.that.does.not.exist", // sample comment, expiry date should go here
     168                "osm-server.version", // remove this around 10/2009
     169                "osm-server.additional-versions", // remove this around 10/2009
     170                null
    167171        };
    168172        for (String i : obsolete) {
    169             if (i == null) continue;
     173            if (i == null) {
     174                continue;
     175            }
    170176            if (Main.pref.hasKey(i)) {
    171177                Main.pref.removeFromCollection(i, Main.pref.get(i));
  • /trunk/src/org/openstreetmap/josm/gui/MapStatus.java

    r2024 r2060  
    173173                            continue;
    174174                        }
    175                         if (osms != null && osms.equals(osmStatus) && ms.modifiers == oldModifiers) {
     175                        if (osms.equals(osmStatus) && ms.modifiers == oldModifiers) {
    176176                            continue;
    177177                        }
     
    194194                            final StringBuilder text = new StringBuilder();
    195195                            String name = osm.getDisplayName(DefaultNameFormatter.getInstance());
    196                             if (osm.id == 0 || osm.modified) {
     196                            if (osm.getId() == 0 || osm.isModified()) {
    197197                                name = "<i><b>"+ osm.getDisplayName(DefaultNameFormatter.getInstance())+"*</b></i>";
    198198                            }
    199199                            text.append(name);
    200                             if (osm.id != 0) {
    201                                 text.append("<br>id="+osm.id);
     200                            if (osm.getId() != 0) {
     201                                text.append("<br>id="+osm.getId());
    202202                            }
    203203                            for (Entry<String, String> e : osm.entrySet()) {
  • /trunk/src/org/openstreetmap/josm/gui/MapView.java

    r2024 r2060  
    4444import org.openstreetmap.josm.gui.layer.MapViewPaintable;
    4545import org.openstreetmap.josm.gui.layer.OsmDataLayer;
    46 import org.openstreetmap.josm.gui.layer.OsmDataLayer.ModifiedChangedListener;
    4746import org.openstreetmap.josm.gui.layer.markerlayer.MarkerLayer;
    4847import org.openstreetmap.josm.gui.layer.markerlayer.PlayHeadMarker;
     
    152151     */
    153152    public void addLayer(Layer layer) {
    154         if (layer instanceof OsmDataLayer) {
    155             OsmDataLayer editLayer = (OsmDataLayer)layer;
    156             editLayer.listenerModified.add(new ModifiedChangedListener(){
    157                 public void modifiedChanged(boolean value, OsmDataLayer source) {
    158                     JOptionPane.getFrameForComponent(Main.parent).setTitle((value?"*":"")
    159                             +tr("Java OpenStreetMap Editor"));
    160                 }
    161             });
    162         }
    163153        if (layer instanceof MarkerLayer && playHeadMarker == null) {
    164154            playHeadMarker = PlayHeadMarker.create();
     
    510500            }
    511501        }
     502        if (layer instanceof OsmDataLayer) {
     503            refreshTitle((OsmDataLayer)layer);
     504        }
    512505
    513506        /* This only makes the buttons look disabled. Disabling the actions as well requires
     
    600593        if (evt.getPropertyName().equals(Layer.VISIBLE_PROP)) {
    601594            repaint();
     595        } else if (evt.getPropertyName().equals(OsmDataLayer.REQUIRES_SAVE_TO_DISK_PROP)
     596                || evt.getPropertyName().equals(OsmDataLayer.REQUIRES_UPLOAD_TO_SERVER_PROP)) {
     597            OsmDataLayer layer = (OsmDataLayer)evt.getSource();
     598            if (layer == getEditLayer()) {
     599                refreshTitle(layer);
     600            }
     601        }
     602    }
     603
     604    protected void refreshTitle(OsmDataLayer layer) {
     605        boolean dirty = layer.requiresSaveToFile() || layer.requiresUploadToServer();
     606        if (dirty) {
     607            JOptionPane.getFrameForComponent(Main.parent).setTitle("* " + tr("Java OpenStreetMap Editor"));
     608        } else {
     609            JOptionPane.getFrameForComponent(Main.parent).setTitle(tr("Java OpenStreetMap Editor"));
    602610        }
    603611    }
  • /trunk/src/org/openstreetmap/josm/gui/NavigatableComponent.java

    r2024 r2060  
    7474        double dist = getDist100Pixel();
    7575        return dist >= 2000 ? Math.round(dist/100)/10 +" km" : (dist >= 1
    76         ? Math.round(dist*10)/10 +" m" : "< 1 m");
     76                ? Math.round(dist*10)/10 +" m" : "< 1 m");
    7777    }
    7878
     
    112112                        center.east() - getWidth()/2.0*scale,
    113113                        center.north() - getHeight()/2.0*scale),
    114                 new EastNorth(
    115                         center.east() + getWidth()/2.0*scale,
    116                         center.north() + getHeight()/2.0*scale));
     114                        new EastNorth(
     115                                center.east() + getWidth()/2.0*scale,
     116                                center.north() + getHeight()/2.0*scale));
    117117    };
    118118
     
    121121        Bounds b = getProjection().getWorldBoundsLatLon();
    122122        return new ProjectionBounds(getProjection().latlon2eastNorth(b.min),
    123             getProjection().latlon2eastNorth(b.max));
     123                getProjection().latlon2eastNorth(b.max));
    124124    };
    125125
     
    130130                        center.east() - getWidth()/2.0*scale,
    131131                        center.north() - getHeight()/2.0*scale)),
    132                 getProjection().eastNorth2latlon(new EastNorth(
    133                         center.east() + getWidth()/2.0*scale,
    134                         center.north() + getHeight()/2.0*scale)));
     132                        getProjection().eastNorth2latlon(new EastNorth(
     133                                center.east() + getWidth()/2.0*scale,
     134                                center.north() + getHeight()/2.0*scale)));
    135135    };
    136136
     
    189189        if(lon < b.min.lon()) {changed = true; lon = b.min.lon(); }
    190190        else if(lon > b.max.lon()) {changed = true; lon = b.max.lon(); }
    191         if(changed)
    192           newCenter = new CachedLatLon(lat, lon).getEastNorth();
     191        if(changed) {
     192            newCenter = new CachedLatLon(lat, lon).getEastNorth();
     193        }
    193194        if (!newCenter.equals(center)) {
    194195            EastNorth oldCenter = center;
     
    211212            e2 = getProjection().latlon2eastNorth(new LatLon(lat, b.max.lon()));
    212213            d = e2.east() - e1.east();
    213             if(d < width*newScale)
     214            if(d < width*newScale) {
    214215                newScale = Math.max(newScaleH, d/width);
     216            }
    215217        }
    216218        else
    217219        {
    218220            d = d/(l1.greatCircleDistance(l2)*height*10);
    219             if(newScale < d)
     221            if(newScale < d) {
    220222                newScale = d;
     223            }
    221224        }
    222225        if (scale != newScale) {
     
    296299            return null;
    297300        for (Node n : ds.nodes) {
    298             if (n.deleted || n.incomplete) {
     301            if (n.isDeleted() || n.incomplete) {
    299302                continue;
    300303            }
     
    307310            // when multiple nodes on one point, prefer new or selected nodes
    308311            else if(dist == minDistanceSq && minPrimitive != null
    309                     && ((n.id == 0 && n.isSelected())
    310                             || (!minPrimitive.isSelected() && (n.isSelected() || n.id == 0)))) {
     312                    && ((n.getId() == 0 && n.isSelected())
     313                            || (!minPrimitive.isSelected() && (n.isSelected() || n.getId() == 0)))) {
    311314                minPrimitive = n;
    312315            }
     
    327330            return null;
    328331        for (Way w : ds.ways) {
    329             if (w.deleted || w.incomplete) {
     332            if (w.isDeleted() || w.incomplete) {
    330333                continue;
    331334            }
     
    334337            for (Node n : w.getNodes()) {
    335338                i++;
    336                 if (n.deleted || n.incomplete) {
     339                if (n.isDeleted() || n.incomplete) {
    337340                    continue;
    338341                }
     
    451454            return null;
    452455        for (Way w : ds.ways) {
    453             if (w.deleted || w.incomplete) {
     456            if (w.isDeleted() || w.incomplete) {
    454457                continue;
    455458            }
    456459            Node lastN = null;
    457460            for (Node n : w.getNodes()) {
    458                 if (n.deleted || n.incomplete) {
     461                if (n.isDeleted() || n.incomplete) {
    459462                    continue;
    460463                }
     
    477480        }
    478481        for (Node n : ds.nodes) {
    479             if (!n.deleted && !n.incomplete
     482            if (!n.isDeleted() && !n.incomplete
    480483                    && getPoint(n).distanceSq(p) < snapDistance) {
    481484                nearest.add(n);
     
    499502            return null;
    500503        for (Node n : ds.nodes) {
    501             if (!n.deleted && !n.incomplete
     504            if (!n.isDeleted() && !n.incomplete
    502505                    && getPoint(n).distanceSq(p) < snapDistance) {
    503506                nearest.add(n);
  • /trunk/src/org/openstreetmap/josm/gui/PleaseWaitDialog.java

    r2024 r2060  
    8585        setSize(Main.pref.getInteger("progressdialog.size", 600), 120);
    8686    }
    87 
    88     @Override
    89     public void setVisible(boolean visible) {
    90         super.setVisible(visible);
    91         if (visible) {
    92             // make sure this dialog is always on top of the main JOSM window
    93             // and all the other windows (relation editors, detached dialogs, etc.)
    94             //
    95             toFront();
    96         }
    97     }
    9887}
  • /trunk/src/org/openstreetmap/josm/gui/PleaseWaitRunnable.java

    r2024 r2060  
    4545     */
    4646    public PleaseWaitRunnable(String title, boolean ignoreException) {
    47         this(title, new PleaseWaitProgressMonitor(), ignoreException);
     47        this(title, new PleaseWaitProgressMonitor(title), ignoreException);
    4848    }
    4949
    5050    public PleaseWaitRunnable(String title, ProgressMonitor progressMonitor, boolean ignoreException) {
    5151        this.title = title;
    52         this.progressMonitor = progressMonitor == null?new PleaseWaitProgressMonitor():progressMonitor;
     52        this.progressMonitor = progressMonitor == null?new PleaseWaitProgressMonitor(title):progressMonitor;
    5353        this.ignoreException = ignoreException;
    5454        this.progressMonitor.addCancelListener(this);
  • /trunk/src/org/openstreetmap/josm/gui/SelectionManager.java

    r2024 r2060  
    286286            // nodes
    287287            for (Node n : nc.getCurrentDataSet().nodes) {
    288                 if (!n.deleted && !n.incomplete && r.contains(nc.getPoint(n))) {
     288                if (!n.isDeleted() && !n.incomplete && r.contains(nc.getPoint(n))) {
    289289                    selection.add(n);
    290290                }
     
    293293            // ways
    294294            for (Way w : nc.getCurrentDataSet().ways) {
    295                 if (w.deleted || w.getNodesCount() == 0 || w.incomplete) {
     295                if (w.isDeleted() || w.getNodesCount() == 0 || w.incomplete) {
    296296                    continue;
    297297                }
  • /trunk/src/org/openstreetmap/josm/gui/conflict/pair/ListMergeModel.java

    r2024 r2060  
    5656 */
    5757public abstract class ListMergeModel<T> extends Observable {
    58     private static final Logger logger = Logger.getLogger(ListMergeModel.class.getName());
     58    //private static final Logger logger = Logger.getLogger(ListMergeModel.class.getName());
    5959
    6060    public static final String FROZEN_PROP = ListMergeModel.class.getName() + ".frozen";
  • /trunk/src/org/openstreetmap/josm/gui/conflict/pair/ListMerger.java

    r2024 r2060  
    4545 */
    4646public abstract class ListMerger<T> extends JPanel implements PropertyChangeListener, Observer {
    47     private static final Logger logger = Logger.getLogger(ListMerger.class.getName());
     47    //private static final Logger logger = Logger.getLogger(ListMerger.class.getName());
    4848
    4949    protected JTable myEntriesTable;
  • /trunk/src/org/openstreetmap/josm/gui/conflict/pair/nodes/NodeListTableCellRenderer.java

    r2024 r2060  
    2929 */
    3030public  class NodeListTableCellRenderer extends JLabel implements TableCellRenderer {
    31     static private final Logger logger = Logger.getLogger(NodeListTableCellRenderer.class.getName());
    32     private static DecimalFormat COORD_FORMATTER = new DecimalFormat("###0.0000");
     31    //static private final Logger logger = Logger.getLogger(NodeListTableCellRenderer.class.getName());
     32    //private static DecimalFormat COORD_FORMATTER = new DecimalFormat("###0.0000");
    3333    public final static Color BGCOLOR_SELECTED = new Color(143,170,255);
    3434    public final static Color BGCOLOR_EMPTY_ROW = new Color(234,234,234);
     
    6767        //
    6868        sb.append("<strong>id</strong>=")
    69         .append(primitive.id)
     69        .append(primitive.getId())
    7070        .append("<br>");
    7171
     
    168168        reset();
    169169        switch(column) {
    170         case 0:
    171             renderRowId(getModel(table),row, isSelected);
    172             break;
    173         case 1:
    174             if (node == null) {
    175                 renderEmptyRow();
    176             } else {
    177                 renderNode(getModel(table), node, row, isSelected);
    178             }
    179             break;
    180         default:
    181             // should not happen
    182             throw new RuntimeException(tr("unexpected column index. Got {0}", column));
     170            case 0:
     171                renderRowId(getModel(table),row, isSelected);
     172                break;
     173            case 1:
     174                if (node == null) {
     175                    renderEmptyRow();
     176                } else {
     177                    renderNode(getModel(table), node, row, isSelected);
     178                }
     179                break;
     180            default:
     181                // should not happen
     182                throw new RuntimeException(tr("unexpected column index. Got {0}", column));
    183183        }
    184184        return this;
  • /trunk/src/org/openstreetmap/josm/gui/dialogs/LayerListDialog.java

    r2024 r2060  
    4747import org.openstreetmap.josm.gui.MapView;
    4848import org.openstreetmap.josm.gui.SideButton;
     49import org.openstreetmap.josm.gui.io.SaveLayersDialog;
    4950import org.openstreetmap.josm.gui.layer.Layer;
    5051import org.openstreetmap.josm.gui.layer.OsmDataLayer;
     
    6162 */
    6263public class LayerListDialog extends ToggleDialog {
    63     static private final Logger logger = Logger.getLogger(LayerListDialog.class.getName());
     64    //static private final Logger logger = Logger.getLogger(LayerListDialog.class.getName());
    6465
    6566    /** the unique instance of the dialog */
     
    299300        }
    300301
    301         protected boolean confirmSkipSaving(OsmDataLayer layer) {
    302             int result = new ExtendedDialog(Main.parent,
    303                     tr("Unsaved Changes"),
    304                     tr("There are unsaved changes in the layer''{0}''. Delete the layer anwyay?",layer.getName()),
    305                     new String[] {tr("Delete Layer"), tr("Cancel")},
    306                     new String[] {"dialogs/delete.png", "cancel.png"}).getValue();
    307 
    308             return result == 1;
    309         }
    310 
    311         protected boolean confirmDeleteLayer(Layer layer) {
    312             return ConditionalOptionPaneUtil.showConfirmationDialog(
    313                     "delete_layer",
    314                     Main.parent,
    315                     tr("Do you really want to delete layer ''{0}''?", layer.getName()),
    316                     tr("Confirmation"),
    317                     JOptionPane.YES_NO_OPTION,
    318                     JOptionPane.QUESTION_MESSAGE,
    319                     JOptionPane.YES_OPTION);
    320         }
    321 
    322         protected DeleteDecision confirmDeleteMultipleLayer(Layer layer, int idx, int numLayers) {
    323             String options[] = new String[] {
    324                     tr("Yes"),
    325                     tr("No"),
    326                     tr("Delete all"),
    327                     tr("Cancel")
    328             };
    329             int ret = ConditionalOptionPaneUtil.showOptionDialog(
    330                     "delete_layer",
    331                     Main.parent,
    332                     tr("Do you really want to delete layer ''{0}''?", layer.getName()),
    333                     tr("Deleting layer {0} of {1}", idx+1, numLayers),
    334                     JOptionPane.DEFAULT_OPTION,
    335                     JOptionPane.QUESTION_MESSAGE,
    336                     options,
    337                     options[0]
    338             );
    339             switch(ret) {
    340                 case ConditionalOptionPaneUtil.DIALOG_DISABLED_OPTION: return DeleteDecision.deleteAll;
    341                 case JOptionPane.CLOSED_OPTION: return DeleteDecision.cancel;
    342                 case 0: return DeleteDecision.deleteCurrent;
    343                 case 1: return DeleteDecision.dontDeleteCurrent;
    344                 case 2: return DeleteDecision.deleteAll;
    345                 case 3: return DeleteDecision.cancel;
    346                 default:
    347                     // shouldn't happen. This is the safest option.
    348                     return DeleteDecision.cancel;
    349             }
    350         }
    351 
    352 
    353         public void deleteSingleLayer(Layer layer) {
    354             if (layer == null)
     302        protected boolean enforceUploadOrSaveModifiedData(List<Layer> selectedLayers) {
     303            SaveLayersDialog dialog = new SaveLayersDialog(Main.parent);
     304            List<OsmDataLayer> layersWithUnmodifiedChanges = new ArrayList<OsmDataLayer>();
     305            for (Layer l: selectedLayers) {
     306                if (! (l instanceof OsmDataLayer)) {
     307                    continue;
     308                }
     309                OsmDataLayer odl = (OsmDataLayer)l;
     310                if (odl.requiresSaveToFile() || odl.requiresUploadToServer()) {
     311                    layersWithUnmodifiedChanges.add(odl);
     312                }
     313            }
     314            dialog.prepareForSavingAndUpdatingLayersBeforeDelete();
     315            if (!layersWithUnmodifiedChanges.isEmpty()) {
     316                dialog.getModel().populate(layersWithUnmodifiedChanges);
     317                dialog.setVisible(true);
     318                switch(dialog.getUserAction()) {
     319                case CANCEL: return false;
     320                case PROCEED: return true;
     321                default: return false;
     322                }
     323            }
     324            return true;
     325        }
     326
     327        public void actionPerformed(ActionEvent e) {
     328            List<Layer> selectedLayers;
     329            if (this.layer == null) {
     330                selectedLayers = getModel().getSelectedLayers();
     331            } else {
     332                selectedLayers = Collections.singletonList(this.layer);
     333            }
     334            if (selectedLayers.isEmpty())
    355335                return;
    356             if (layer instanceof OsmDataLayer) {
    357                 OsmDataLayer dataLayer = (OsmDataLayer)layer;
    358                 if (dataLayer.isModified()) {
    359                     if (! confirmSkipSaving(dataLayer))
    360                         return;
    361                 }
    362                 else if (!confirmDeleteLayer(dataLayer))
    363                     return;
    364             } else {
    365                 if (!confirmDeleteLayer(layer))
    366                     return;
    367             }
    368             // model and view are going to be updated via LayerChangeListener
    369             //
    370             Main.main.removeLayer(layer);
    371         }
    372 
    373         public void deleteMultipleLayers(List<Layer> layers) {
    374             boolean doAskConfirmation = true;
    375             for (int i=0; i < layers.size(); i++) {
    376                 Layer layer = layers.get(i);
    377                 if (layer instanceof OsmDataLayer) {
    378                     OsmDataLayer dataLayer = (OsmDataLayer)layer;
    379                     if (dataLayer.isModified() && ! confirmSkipSaving(dataLayer)) {
    380                         continue;
    381                     }
    382                 }
    383                 if (doAskConfirmation) {
    384                     DeleteDecision decision = confirmDeleteMultipleLayer(layer, i, layers.size());
    385                     switch(decision) {
    386                         case deleteCurrent: /* do nothing */ break;
    387                         case deleteAll: doAskConfirmation = false; break;
    388                         case dontDeleteCurrent: continue;
    389                         case cancel: return;
    390                     }
    391                 }
    392                 // model and view are going to be updated via LayerChangeListener
    393                 //
    394                 Main.main.removeLayer(layer);
    395             }
    396         }
    397 
    398         public void actionPerformed(ActionEvent e) {
    399             if (this.layer == null) {
    400                 List<Layer> selectedLayers = getModel().getSelectedLayers();
    401                 if (selectedLayers.isEmpty())
    402                     return;
    403                 if (selectedLayers.size() == 1) {
    404                     deleteSingleLayer(selectedLayers.get(0));
    405                 } else {
    406                     deleteMultipleLayers(selectedLayers);
    407                 }
    408             } else {
    409                 deleteSingleLayer(this.layer);
     336            if (! enforceUploadOrSaveModifiedData(selectedLayers))
     337                return;
     338            for(Layer l: selectedLayers) {
     339                Main.main.removeLayer(l);
    410340            }
    411341        }
  • /trunk/src/org/openstreetmap/josm/gui/dialogs/PropertiesDialog.java

    r2024 r2060  
    306306    void membershipEdit(int row) {
    307307        Relation relation = (Relation)membershipData.getValueAt(row, 0);
    308         Main.main.map.relationListDialog.selectRelation(relation);
     308        Main.map.relationListDialog.selectRelation(relation);
    309309        RelationEditor.getEditor(
    310310                Main.map.mapView.getEditLayer(),
     
    474474                            c.setFont(c.getFont().deriveFont(Font.ITALIC));
    475475                        } else {
    476                             final Map.Entry entry = (Map.Entry) v.entrySet().iterator().next(); 
     476                            final Map.Entry entry = (Map.Entry) v.entrySet().iterator().next();
    477477                            str = (String) entry.getKey();
    478478                        }
     
    636636        }
    637637
    638         LinkedList<TaggingPreset> p = new LinkedList<TaggingPreset>();
    639638        presets.removeAll();
    640639        int total = nodes+ways+relations+closedways;
     
    751750        if (Main.main.getCurrentDataSet() != null) {
    752751            for (Relation r : Main.main.getCurrentDataSet().relations) {
    753                 if (!r.deleted && !r.incomplete) {
     752                if (!r.isDeleted() && !r.incomplete) {
    754753                    for (RelationMember m : r.getMembers()) {
    755754                        if (newSelection.contains(m.getMember())) {
     
    831830        protected void deleteFromRelation(int row) {
    832831            Relation cur = (Relation)membershipData.getValueAt(row, 0);
    833             int result = new ExtendedDialog(Main.parent,
     832
     833            ExtendedDialog ed = new ExtendedDialog(Main.parent,
    834834                    tr("Change relation"),
    835                     tr("Really delete selection from relation {0}?", cur.getDisplayName(DefaultNameFormatter.getInstance())),
    836                     new String[] {tr("Delete from relation"), tr("Cancel")},
    837                     new String[] {"dialogs/delete.png", "cancel.png"}).getValue();
    838 
    839             if(result != 1)
     835                    new String[] {tr("Delete from relation"), tr("Cancel")});
     836            ed.setButtonIcons(new String[] {"dialogs/delete.png", "cancel.png"});
     837            ed.setContent(tr("Really delete selection from relation {0}?", cur.getDisplayName(DefaultNameFormatter.getInstance())));
     838            ed.showDialog();
     839
     840            if(ed.getValue() != 1)
    840841                return;
    841842
    842843            Relation rel = new Relation(cur);
    843844            Collection<OsmPrimitive> sel = Main.main.getCurrentDataSet().getSelected();
    844             int index = 0;
    845             for (RelationMember rm : cur.getMembers()) {
    846                 for (OsmPrimitive osm : sel) {
    847                     if (rm.getMember() == osm)
    848                     {
    849                         rel.removeMember(index);
    850                         break;
    851                     }
    852                 }
    853                 index++;
     845            for (OsmPrimitive primitive: sel) {
     846                rel.removeMembersFor(primitive);
    854847            }
    855848            Main.main.undoRedo.add(new ChangeCommand(cur, rel));
  • /trunk/src/org/openstreetmap/josm/gui/dialogs/RelationListDialog.java

    r2024 r2060  
    135135            int i = 0;
    136136            for (OsmPrimitive e : DataSet.sort(Main.main.getCurrentDataSet().relations)) {
    137                 if (!e.deleted && !e.incomplete) {
     137                if (!e.isDeleted() && !e.incomplete) {
    138138                    list.setElementAt(e, i++);
    139139                }
     
    381381            Relation copy = new Relation();
    382382            copy.cloneFrom(original);
     383            // FIXME: id is going to be hidden. How to reset a primitive?
     384            //
    383385            copy.id = 0;
    384             copy.modified = true;
     386            copy.setModified(true);
    385387            RelationEditor editor = RelationEditor.getEditor(
    386388                    Main.main.getEditLayer(),
  • /trunk/src/org/openstreetmap/josm/gui/dialogs/UserListDialog.java

    r2024 r2060  
    33
    44import static org.openstreetmap.josm.tools.I18n.tr;
     5import static org.openstreetmap.josm.tools.I18n.trn;
    56
    67import java.awt.BorderLayout;
     8import java.awt.FlowLayout;
     9import java.awt.event.ActionEvent;
    710import java.awt.event.KeyEvent;
     11import java.awt.event.MouseAdapter;
    812import java.awt.event.MouseEvent;
    9 import java.awt.event.MouseListener;
    10 import java.util.Arrays;
     13import java.io.UnsupportedEncodingException;
     14import java.net.URLEncoder;
     15import java.text.NumberFormat;
     16import java.util.ArrayList;
    1117import java.util.Collection;
    12 import java.util.Comparator;
     18import java.util.Collections;
    1319import java.util.HashMap;
     20import java.util.HashSet;
     21import java.util.Iterator;
    1422import java.util.LinkedList;
    15 
     23import java.util.List;
     24import java.util.Map;
     25import java.util.Set;
     26
     27import javax.swing.AbstractAction;
     28import javax.swing.JOptionPane;
     29import javax.swing.JPanel;
    1630import javax.swing.JScrollPane;
    1731import javax.swing.JTable;
    1832import javax.swing.ListSelectionModel;
     33import javax.swing.event.ListSelectionEvent;
     34import javax.swing.event.ListSelectionListener;
    1935import javax.swing.table.DefaultTableModel;
    2036
    2137import org.openstreetmap.josm.Main;
     38import org.openstreetmap.josm.actions.AbstractInfoAction;
    2239import org.openstreetmap.josm.data.SelectionChangedListener;
    2340import org.openstreetmap.josm.data.osm.DataSet;
    2441import org.openstreetmap.josm.data.osm.OsmPrimitive;
    2542import org.openstreetmap.josm.data.osm.User;
     43import org.openstreetmap.josm.gui.SideButton;
    2644import org.openstreetmap.josm.gui.layer.Layer;
    2745import org.openstreetmap.josm.gui.layer.OsmDataLayer;
    2846import org.openstreetmap.josm.gui.layer.Layer.LayerChangeListener;
     47import org.openstreetmap.josm.tools.ImageProvider;
    2948import org.openstreetmap.josm.tools.Shortcut;
    3049
     
    3352 * selection area, along with the number of objects.
    3453 *
    35  * @author Frederik Ramm <frederik@remote.org>
    3654 */
    37 public class UserListDialog extends ToggleDialog implements SelectionChangedListener, MouseListener, LayerChangeListener {
     55public class UserListDialog extends ToggleDialog implements SelectionChangedListener, LayerChangeListener {
    3856
    3957    /**
    4058     * The display list.
    4159     */
    42     private final DefaultTableModel data = new DefaultTableModel() {
    43         @Override public boolean isCellEditable(int row, int column) {
    44             return false;
    45         }
    46         @Override public Class<?> getColumnClass(int columnIndex) {
    47             return columnIndex == 0 ? String.class : Integer.class;
    48         }
    49     };
    50 
    51     private JTable userTable = new JTable(data);
    52 
    53     private static User anonymousUser = User.get("(anonymous users)");
     60    private JTable userTable;
     61    private UserTableModel model;
     62    private SelectUsersPrimitivesAction selectionUsersPrimitivesAction;
     63    private ShowUserInfoAction showUserInfoAction;
    5464
    5565    public UserListDialog() {
     
    5767                Shortcut.registerShortcut("subwindow:authors", tr("Toggle: {0}", tr("Authors")), KeyEvent.VK_A, Shortcut.GROUP_LAYER, Shortcut.SHIFT_DEFAULT), 150);
    5868
    59         data.setColumnIdentifiers(new String[]{tr("Author"),tr("# Objects"),"%"});
    60         userTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    61         add(new JScrollPane(userTable), BorderLayout.CENTER);
    62         if (Main.main.getCurrentDataSet() != null) {
    63             selectionChanged(Main.main.getCurrentDataSet().getSelected());
    64         }
    65         userTable.addMouseListener(this);
     69        build();
    6670        DataSet.selListeners.add(this);
    6771        Layer.listeners.add(this);
    6872    }
    6973
    70     @Override public void setVisible(boolean b) {
    71         super.setVisible(b);
    72         if (b && Main.main.getCurrentDataSet() != null) {
    73             selectionChanged(Main.main.getCurrentDataSet().getSelected());
    74         }
     74    protected JPanel buildButtonRow() {
     75        JPanel pnl = new JPanel();
     76        pnl.setLayout(new FlowLayout(FlowLayout.LEFT));
     77
     78        // -- select users primitives action
     79        //
     80        selectionUsersPrimitivesAction = new SelectUsersPrimitivesAction();
     81        userTable.getSelectionModel().addListSelectionListener(selectionUsersPrimitivesAction);
     82        pnl.add(new SideButton(selectionUsersPrimitivesAction));
     83
     84        // -- info action
     85        //
     86        showUserInfoAction = new ShowUserInfoAction();
     87        userTable.getSelectionModel().addListSelectionListener(showUserInfoAction);
     88        pnl.add(new SideButton(showUserInfoAction));
     89        return pnl;
     90    }
     91
     92    protected void build() {
     93        JPanel pnl = new JPanel();
     94        pnl.setLayout(new BorderLayout());
     95        model = new UserTableModel();
     96        userTable = new JTable(model);
     97        userTable.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
     98        pnl.add(new JScrollPane(userTable), BorderLayout.CENTER);
     99
     100        // -- the button row
     101        pnl.add(buildButtonRow(), BorderLayout.SOUTH);
     102        userTable.addMouseListener(new DoubleClickAdapter());
     103        add(pnl, BorderLayout.CENTER);
    75104    }
    76105
     
    80109     */
    81110    public void selectionChanged(Collection<? extends OsmPrimitive> newSelection) {
    82         if (!isVisible())
    83             return;
    84 
    85         class UserCount {
    86             User user;
    87             int count;
    88             UserCount(User user, int count) { this.user=user; this.count=count; }
    89         }
    90 
    91         if (data == null)
    92             return; // selection changed may be received in base class constructor before init
    93 
    94         data.setRowCount(0);
    95 
    96         HashMap<User,UserCount> counters = new HashMap<User,UserCount>();
    97         int all = 0;
    98         for (OsmPrimitive p : newSelection) {
    99             User u = p.user;
    100             if (u == null) {
    101                 u = anonymousUser;
    102             }
    103             UserCount uc = counters.get(u);
    104             if (uc == null) {
    105                 counters.put(u, uc = new UserCount(u, 0));
    106             }
    107             uc.count++;
    108             all++;
    109         }
    110         UserCount[] ucArr = new UserCount[counters.size()];
    111         counters.values().toArray(ucArr);
    112         Arrays.sort(ucArr, new Comparator<UserCount>() {
    113             public int compare(UserCount a, UserCount b) {
    114                 return (a.count<b.count) ? 1 : (a.count>b.count) ? -1 : 0;
    115             }
    116         });
    117 
    118         for (UserCount uc : ucArr) {
    119             data.addRow(new Object[] { uc.user.name, uc.count, uc.count * 100 / all });
    120         }
    121 
    122         if(ucArr.length != 0) {
    123             setTitle(tr("Authors: {0}", ucArr.length));
     111        refresh(newSelection);
     112    }
     113
     114    public void activeLayerChange(Layer oldLayer, Layer newLayer) {
     115        if (newLayer instanceof OsmDataLayer) {
     116            refresh(((OsmDataLayer) newLayer).data.getSelected());
     117        } else {
     118            refresh(null);
     119        }
     120    }
     121
     122    public void layerAdded(Layer newLayer) {
     123        // do nothing
     124    }
     125
     126    public void layerRemoved(Layer oldLayer) {
     127        // do nothing
     128    }
     129
     130    public void refresh(Collection<? extends OsmPrimitive> fromPrimitives) {
     131        model.populate(fromPrimitives);
     132        if(model.getRowCount() != 0) {
     133            setTitle(trn("{0} Author", "{0} Authors", model.getRowCount() , model.getRowCount()));
    124134        } else {
    125135            setTitle(tr("Authors"));
     
    127137    }
    128138
    129     public void mouseClicked(MouseEvent e) {
    130         if (e.getButton() == MouseEvent.BUTTON1 && e.getClickCount()==2) {
    131             int index = userTable.getSelectedRow();
    132             String userName = (String) data.getValueAt(index, 0);
    133             if (userName==null)
    134                 return;
     139    class SelectUsersPrimitivesAction extends AbstractAction implements ListSelectionListener{
     140        public SelectUsersPrimitivesAction() {
     141            putValue(NAME, tr("Select"));
     142            putValue(SHORT_DESCRIPTION, tr("Select primitives submitted by this user"));
     143            putValue(SMALL_ICON, ImageProvider.get("dialogs", "select"));
     144            updateEnabledState();
     145        }
     146
     147        public void select() {
     148            int indexes[] = userTable.getSelectedRows();
     149            if (indexes == null || indexes.length == 0) return;
     150            model.selectPrimitivesOwnedBy(userTable.getSelectedRows());
     151        }
     152
     153        public void actionPerformed(ActionEvent e) {
     154            select();
     155        }
     156
     157        protected void updateEnabledState() {
     158            setEnabled(userTable != null && userTable.getSelectedRowCount() > 0);
     159        }
     160
     161        public void valueChanged(ListSelectionEvent e) {
     162            updateEnabledState();
     163        }
     164    }
     165
     166    /**
     167     * Action for launching the info page of a user
     168     */
     169    class ShowUserInfoAction extends AbstractInfoAction implements ListSelectionListener {
     170
     171        public ShowUserInfoAction() {
     172            putValue(NAME, tr("Show info"));
     173            putValue(SHORT_DESCRIPTION, tr("Launches a browser with information about the user"));
     174            putValue(SMALL_ICON, ImageProvider.get("about"));
     175            updateEnabledState();
     176        }
     177
     178        @Override
     179        public void actionPerformed(ActionEvent e) {
     180            int rows[] = userTable.getSelectedRows();
     181            if (rows == null || rows.length == 0) return;
     182            List<User> users = model.getSelectedUsers(rows);
     183            if (users.isEmpty()) return;
     184            if (users.size() > 10) {
     185                System.out.println(tr("Warning: only launching info browsers for the first {0} of {1} selected users", 10, users.size()));
     186            }
     187            int num = Math.min(10, users.size());
     188            Iterator<User> it = users.iterator();
     189            while(it.hasNext() && num > 0) {
     190                String url = createInfoUrl(it.next());
     191                if (url == null) {
     192                    break;
     193                }
     194                launchBrowser(url);
     195                num--;
     196            }
     197        }
     198
     199        @Override
     200        protected String createInfoUrl(Object infoObject) {
     201            User user = (User)infoObject;
     202            try {
     203                return getBaseUserUrl() + "/" + URLEncoder.encode(user.name, "UTF-8");
     204            } catch(UnsupportedEncodingException e) {
     205                e.printStackTrace();
     206                JOptionPane.showMessageDialog(
     207                        Main.parent,
     208                        tr("<html>Failed to create an URL because the encoding ''{0}'' was<br>"
     209                                + "was missing on this system.</html>", "UTF-8"),
     210                                tr("Missing encoding"),
     211                                JOptionPane.ERROR_MESSAGE
     212                );
     213                return null;
     214            }
     215        }
     216
     217        @Override
     218        protected void updateEnabledState() {
     219            setEnabled(userTable != null && userTable.getSelectedRowCount() > 0);
     220        }
     221
     222        public void valueChanged(ListSelectionEvent e) {
     223            updateEnabledState();
     224        }
     225    }
     226
     227    class DoubleClickAdapter extends MouseAdapter {
     228        @Override
     229        public void mouseClicked(MouseEvent e) {
     230            if (e.getButton() == MouseEvent.BUTTON1 && e.getClickCount()==2) {
     231                selectionUsersPrimitivesAction.select();
     232            }
     233        }
     234    }
     235
     236    /**
     237     * Action for selecting the primitives contributed by the currently selected
     238     * users.
     239     *
     240     */
     241    private static class UserInfo implements Comparable<UserInfo> {
     242        public User user;
     243        public int count;
     244        public double percent;
     245        UserInfo(User user, int count, double percent) {
     246            this.user=user;
     247            this.count=count;
     248            this.percent = percent;
     249        }
     250        public int compareTo(UserInfo o) {
     251            if (count < o.count) return 1;
     252            if (count > o.count) return -1;
     253            if (user== null || user.name == null) return 1;
     254            if (o.user == null || o.user.name == null) return -1;
     255            return user.name.compareTo(o.user.name);
     256        }
     257
     258        public String getName() {
     259            if (user == null) return null;
     260            return user.name;
     261        }
     262    }
     263
     264    /**
     265     * The table model for the users
     266     *
     267     */
     268    class UserTableModel extends DefaultTableModel {
     269        private ArrayList<UserInfo> data;
     270
     271        public UserTableModel() {
     272            setColumnIdentifiers(new String[]{tr("Author"),tr("# Objects"),"%"});
     273            data = new ArrayList<UserInfo>();
     274        }
     275
     276        protected Map<User, Integer> computeStatistics(Collection<? extends OsmPrimitive> primitives) {
     277            HashMap<User, Integer> ret = new HashMap<User, Integer>();
     278            if (primitives == null || primitives.isEmpty()) return ret;
     279            for (OsmPrimitive primitive: primitives) {
     280                if (primitive.user == null) {
     281                    continue;
     282                }
     283                if (ret.containsKey(primitive.user)) {
     284                    ret.put(primitive.user, ret.get(primitive.user) + 1);
     285                } else {
     286                    ret.put(primitive.user, 1);
     287                }
     288            }
     289            return ret;
     290        }
     291
     292        public void populate(Collection<? extends OsmPrimitive> primitives) {
     293            Map<User,Integer> statistics = computeStatistics(primitives);
     294            data.clear();
     295            if (primitives != null) {
     296                for (Map.Entry<User, Integer> entry: statistics.entrySet()) {
     297                    data.add(new UserInfo(entry.getKey(), entry.getValue(), (double)entry.getValue() /  (double)primitives.size()));
     298                }
     299            }
     300            Collections.sort(data);
     301            fireTableDataChanged();
     302        }
     303
     304        @Override
     305        public int getRowCount() {
     306            if (data == null) return 0;
     307            return data.size();
     308        }
     309
     310        @Override
     311        public Object getValueAt(int row, int column) {
     312            UserInfo info = data.get(row);
     313            switch(column) {
     314                case 0: /* author */ return info.getName() == null ? "" : info.getName();
     315                case 1: /* count */ return info.count;
     316                case 2: /* percent */ return NumberFormat.getPercentInstance().format(info.percent);
     317            }
     318            return null;
     319        }
     320
     321        @Override
     322        public boolean isCellEditable(int row, int column) {
     323            return false;
     324        }
     325
     326        public void selectPrimitivesOwnedBy(int [] rows) {
     327            Set<User> users= new HashSet<User>();
     328            for (int index: rows) {
     329                if (data.get(index).user == null) {
     330                    continue;
     331                }
     332                users.add(data.get(index).user);
     333            }
    135334            Collection<OsmPrimitive> selected = Main.main.getCurrentDataSet().getSelected();
    136335            Collection<OsmPrimitive> byUser = new LinkedList<OsmPrimitive>();
    137336            for (OsmPrimitive p : selected) {
    138                 if (p.user!= null && userName.equals(p.user.name)) {
     337                if (p.user == null) {
     338                    continue;
     339                }
     340                if (users.contains(p.user)) {
    139341                    byUser.add(p);
    140342                }
     
    142344            Main.main.getCurrentDataSet().setSelected(byUser);
    143345        }
    144     }
    145 
    146     public void mouseEntered(MouseEvent e) {
    147     }
    148 
    149     public void mouseExited(MouseEvent e) {
    150     }
    151 
    152     public void mousePressed(MouseEvent e) {
    153     }
    154 
    155     public void mouseReleased(MouseEvent e) {
    156     }
    157 
    158     public void activeLayerChange(Layer oldLayer, Layer newLayer) {
    159         if (newLayer instanceof OsmDataLayer) {
    160             OsmDataLayer dataLayer = (OsmDataLayer)newLayer;
    161             selectionChanged(dataLayer.data.getSelected());
    162 
    163         }
    164     }
    165 
    166     public void layerAdded(Layer newLayer) {
    167         // do nothing
    168     }
    169 
    170     public void layerRemoved(Layer oldLayer) {
    171         // do nothing
     346
     347        public List<User> getSelectedUsers(int rows[]) {
     348            LinkedList<User> ret = new LinkedList<User>();
     349            if (rows == null || rows.length == 0) return ret;
     350            for (int row: rows) {
     351                if (data.get(row).user == null) {
     352                    continue;
     353                }
     354                ret.add(data.get(row).user);
     355            }
     356            return ret;
     357        }
    172358    }
    173359}
  • /trunk/src/org/openstreetmap/josm/gui/dialogs/relation/GenericRelationEditor.java

    r2024 r2060  
    1111import java.awt.Insets;
    1212import java.awt.event.ActionEvent;
    13 import java.awt.event.ComponentAdapter;
    14 import java.awt.event.ComponentEvent;
    1513import java.awt.event.FocusAdapter;
    1614import java.awt.event.FocusEvent;
     
    6866import org.openstreetmap.josm.gui.PleaseWaitRunnable;
    6967import org.openstreetmap.josm.gui.SideButton;
    70 import org.openstreetmap.josm.gui.dialogs.relation.ac.AutoCompletionCache;
    71 import org.openstreetmap.josm.gui.dialogs.relation.ac.AutoCompletionList;
    7268import org.openstreetmap.josm.gui.layer.OsmDataLayer;
    7369import org.openstreetmap.josm.gui.progress.PleaseWaitProgressMonitor;
    7470import org.openstreetmap.josm.gui.progress.ProgressMonitor;
     71import org.openstreetmap.josm.gui.tagging.AutoCompletingTextField;
     72import org.openstreetmap.josm.gui.tagging.TagCellEditor;
     73import org.openstreetmap.josm.gui.tagging.TagEditorModel;
     74import org.openstreetmap.josm.gui.tagging.TagTable;
     75import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionCache;
     76import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionList;
    7577import org.openstreetmap.josm.io.OsmApi;
    7678import org.openstreetmap.josm.io.OsmServerObjectReader;
     
    123125        //
    124126        acCache = AutoCompletionCache.getCacheForLayer(getLayer());
    125         acCache.initFromJOSMDataset();
     127        acCache.initFromDataSet();
    126128        acList = new AutoCompletionList();
    127129
     
    268270        final JScrollPane scrollPane = new JScrollPane(tagTable);
    269271
    270         // this adapters ensures that the width of the tag table columns is adjusted
    271         // to the width of the scroll pane viewport. Also tried to overwrite
    272         // getPreferredViewportSize() in JTable, but did not work.
    273         //
    274         scrollPane.addComponentListener(new ComponentAdapter() {
    275             @Override
    276             public void componentResized(ComponentEvent e) {
    277                 super.componentResized(e);
    278                 Dimension d = scrollPane.getViewport().getExtentSize();
    279                 tagTable.adjustColumnWidth(d.width);
    280             }
    281         });
    282 
    283272        GridBagConstraints gc = new GridBagConstraints();
    284273        gc.gridx = 0;
     
    330319
    331320        final JScrollPane scrollPane = new JScrollPane(memberTable);
    332         // this adapters ensures that the width of the tag table columns is adjusted
    333         // to the width of the scroll pane viewport. Also tried to overwrite
    334         // getPreferredViewportSize() in JTable, but did not work.
    335         //
    336         scrollPane.addComponentListener(new ComponentAdapter() {
    337             @Override
    338             public void componentResized(ComponentEvent e) {
    339                 super.componentResized(e);
    340                 Dimension d = scrollPane.getViewport().getExtentSize();
    341                 memberTable.adjustColumnWidth(d.width);
    342             }
    343         });
    344321
    345322        GridBagConstraints gc = new GridBagConstraints();
     
    13551332
    13561333        protected void updateEnabledState() {
    1357             setEnabled(getRelation() != null && getRelation().id > 0);
     1334            setEnabled(getRelation() != null && getRelation().getId() > 0);
    13581335        }
    13591336    }
     
    15591536            try {
    15601537                progressMonitor.indeterminateSubTask("");
    1561                 OsmServerObjectReader reader = new OsmServerObjectReader(getRelation().id, OsmPrimitiveType.RELATION,
     1538                OsmServerObjectReader reader = new OsmServerObjectReader(getRelation().getId(), OsmPrimitiveType.RELATION,
    15621539                        true);
    15631540                DataSet dataSet = reader.parseOsm(progressMonitor
  • /trunk/src/org/openstreetmap/josm/gui/dialogs/relation/MemberRoleCellEditor.java

    r2024 r2060  
    99import javax.swing.table.TableCellEditor;
    1010
    11 import org.openstreetmap.josm.gui.dialogs.relation.ac.AutoCompletionCache;
    12 import org.openstreetmap.josm.gui.dialogs.relation.ac.AutoCompletionItemPritority;
    13 import org.openstreetmap.josm.gui.dialogs.relation.ac.AutoCompletionList;
    14 import org.openstreetmap.josm.gui.dialogs.relation.ac.AutoCompletionListItem;
     11import org.openstreetmap.josm.gui.tagging.AutoCompletingTextField;
     12import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionCache;
     13import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionItemPritority;
     14import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionList;
     15import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionListItem;
    1516
    1617public class MemberRoleCellEditor extends AbstractCellEditor implements TableCellEditor {
  • /trunk/src/org/openstreetmap/josm/gui/dialogs/relation/MemberTable.java

    r2024 r2060  
    44import static org.openstreetmap.josm.tools.I18n.tr;
    55
     6import java.awt.Container;
     7import java.awt.Dimension;
    68import java.awt.event.ActionEvent;
    79import java.awt.event.KeyEvent;
     
    1315import javax.swing.JPopupMenu;
    1416import javax.swing.JTable;
     17import javax.swing.JViewport;
    1518import javax.swing.KeyStroke;
    1619import javax.swing.ListSelectionModel;
     
    7275    }
    7376
    74     /**
    75      * adjusts the width of the columns for the tag name and the tag value to the width of the
    76      * scroll panes viewport.
    77      *
    78      * Note: {@see #getPreferredScrollableViewportSize()} did not work as expected
    79      *
    80      * @param scrollPaneWidth the width of the scroll panes viewport
    81      */
    82     public void adjustColumnWidth(int scrollPaneWidth) {
    83         TableColumnModel tcm = getColumnModel();
    84         int width = scrollPaneWidth;
    85         width = width / 3;
    86         if (width > 0) {
    87             tcm.getColumn(0).setMinWidth(width);
    88             tcm.getColumn(0).setMaxWidth(width);
    89             tcm.getColumn(1).setMinWidth(width);
    90             tcm.getColumn(1).setMaxWidth(width);
    91             tcm.getColumn(2).setMinWidth(width);
    92             tcm.getColumn(2).setMaxWidth(width);
    93 
    94         }
     77    @Override
     78    public Dimension getPreferredSize(){
     79        Container c = getParent();
     80        while(c != null && ! (c instanceof JViewport)) {
     81            c = c.getParent();
     82        }
     83        if (c != null) {
     84            Dimension d = super.getPreferredSize();
     85            d.width = c.getSize().width;
     86            return d;
     87        }
     88        return super.getPreferredSize();
    9589    }
    9690
  • /trunk/src/org/openstreetmap/josm/gui/dialogs/relation/ReferringRelationsBrowser.java

    r2024 r2060  
    107107                    getLayer(),
    108108                    full,
    109                     new PleaseWaitProgressMonitor()
     109                    new PleaseWaitProgressMonitor(tr("Loading parent relations"))
    110110            );
    111111            task.setContinuation(
  • /trunk/src/org/openstreetmap/josm/gui/history/HistoryBrowserModel.java

    r2024 r2060  
    296296            return p.equals(reference);
    297297        }
     298
     299        public HistoryOsmPrimitive getPrimitive(int row) {
     300            return history.get(row);
     301        }
    298302    }
    299303
  • /trunk/src/org/openstreetmap/josm/gui/history/VersionInfoPanel.java

    r2024 r2060  
    55
    66import java.awt.BorderLayout;
     7import java.awt.event.ActionEvent;
     8import java.awt.event.MouseEvent;
    79import java.text.SimpleDateFormat;
    810import java.util.Observable;
     
    1214import javax.swing.JPanel;
    1315
     16import org.openstreetmap.josm.actions.AbstractInfoAction;
    1417import org.openstreetmap.josm.data.osm.history.HistoryOsmPrimitive;
     18import org.openstreetmap.josm.tools.ImageProvider;
    1519
    1620/**
     
    4246        if (primitive == null)
    4347            return "";
     48        String url = AbstractInfoAction.getBaseBrowseUrl() + "/changeset/" + primitive.getChangesetId();
    4449        String text = tr(
    45                 "<html>Version <strong>{0}</strong> created on <strong>{1}</strong> by <strong>{2}</strong></html>",
     50                "<html>Version <strong>{0}</strong> created on <strong>{1}</strong> by <strong>{2}</strong> in changeset <strong>{3}</strong>",
    4651                Long.toString(primitive.getVersion()),
    4752                new SimpleDateFormat().format(primitive.getTimestamp()),
    48                 primitive.getUser()
     53                primitive.getUser(),
     54                primitive.getChangesetId()
    4955        );
    5056        return text;
  • /trunk/src/org/openstreetmap/josm/gui/history/VersionTable.java

    r2024 r2060  
    22package org.openstreetmap.josm.gui.history;
    33
     4import static org.openstreetmap.josm.tools.I18n.tr;
     5
     6import java.awt.event.ActionEvent;
    47import java.awt.event.MouseAdapter;
    58import java.awt.event.MouseEvent;
     
    912
    1013import javax.swing.DefaultListSelectionModel;
     14import javax.swing.JPopupMenu;
    1115import javax.swing.JTable;
    1216import javax.swing.ListSelectionModel;
    1317import javax.swing.event.ListSelectionEvent;
    1418import javax.swing.event.ListSelectionListener;
     19
     20import org.openstreetmap.josm.actions.AbstractInfoAction;
     21import org.openstreetmap.josm.data.osm.history.HistoryOsmPrimitive;
     22import org.openstreetmap.josm.tools.ImageProvider;
    1523
    1624/**
     
    2230
    2331    private static Logger logger = Logger.getLogger(VersionTable.class.getName());
     32    private VersionTablePopupMenu popupMenu;
    2433
    2534    protected void build() {
     
    2736        addMouseListener(new MouseHandler());
    2837        getSelectionModel().addListSelectionListener(new SelectionHandler());
     38        popupMenu = new VersionTablePopupMenu();
     39        addMouseListener(new PopupMenuTrigger());
    2940    }
    3041
     
    3647
    3748    protected void handleSelectReferencePointInTime(int row) {
    38         getVesionTableModel().setReferencePointInTime(row);
     49        getVersionTableModel().setReferencePointInTime(row);
    3950    }
    4051
    4152    protected void handleSelectCurrentPointInTime(int row) {
    42         getVesionTableModel().setCurrentPointInTime(row);
     53        getVersionTableModel().setCurrentPointInTime(row);
    4354    }
    4455
    45     protected HistoryBrowserModel.VersionTableModel getVesionTableModel() {
     56    protected HistoryBrowserModel.VersionTableModel getVersionTableModel() {
    4657        return (HistoryBrowserModel.VersionTableModel) getModel();
    4758    }
     
    7384        repaint();
    7485    }
     86
     87    protected void showPopupMenu(MouseEvent evt) {
     88        HistoryBrowserModel.VersionTableModel model = getVersionTableModel();
     89        int row = getSelectedRow();
     90        if (row == -1) {
     91            row = rowAtPoint(evt.getPoint());
     92        }
     93        HistoryOsmPrimitive primitive = model.getPrimitive(row);
     94        popupMenu.prepare(primitive);
     95        popupMenu.show(evt.getComponent(), evt.getX(), evt.getY());
     96    }
     97
     98    class PopupMenuTrigger extends MouseAdapter {
     99        @Override
     100        public void mousePressed(MouseEvent e) {
     101            showPopup(e);
     102        }
     103        @Override
     104        public void mouseReleased(MouseEvent e) {
     105            showPopup(e);
     106        }
     107        private void showPopup(MouseEvent e) {
     108            if (e.isPopupTrigger()) {
     109                showPopupMenu(e);
     110            }
     111        }
     112    }
     113
     114    class ChangesetInfoAction extends AbstractInfoAction {
     115        private HistoryOsmPrimitive primitive;
     116
     117        public ChangesetInfoAction() {
     118            putValue(NAME, tr("Changeset info"));
     119            putValue(SHORT_DESCRIPTION, tr("Launch browser with information about the changeset"));
     120            putValue(SMALL_ICON, ImageProvider.get("about"));
     121        }
     122
     123        @Override
     124        protected String createInfoUrl(Object infoObject) {
     125            HistoryOsmPrimitive primitive = (HistoryOsmPrimitive) infoObject;
     126            return getBaseBrowseUrl() + "/changeset/" + primitive.getChangesetId();
     127        }
     128
     129        @Override
     130        public void actionPerformed(ActionEvent e) {
     131            if (!isEnabled())
     132                return;
     133            String url = createInfoUrl(primitive);
     134            launchBrowser(url);
     135        }
     136
     137        public void prepare(HistoryOsmPrimitive primitive) {
     138            putValue(NAME, tr("Show changeset {0}", primitive.getChangesetId()));
     139            this.primitive = primitive;
     140        }
     141    }
     142
     143    class VersionTablePopupMenu extends JPopupMenu {
     144
     145        private ChangesetInfoAction changesetInfoAction;
     146
     147        protected void build() {
     148            changesetInfoAction = new ChangesetInfoAction();
     149            add(changesetInfoAction);
     150        }
     151        public VersionTablePopupMenu() {
     152            super();
     153            build();
     154        }
     155
     156        public void prepare(HistoryOsmPrimitive primitive) {
     157            changesetInfoAction.prepare(primitive);
     158            invalidate();
     159        }
     160    }
    75161}
  • /trunk/src/org/openstreetmap/josm/gui/layer/GpxLayer.java

    r2024 r2060  
    895895                }
    896896            }
    897             new DownloadOsmTaskList().download(false, toDownload, new PleaseWaitProgressMonitor());
     897            new DownloadOsmTaskList().download(false, toDownload, new PleaseWaitProgressMonitor(tr("Download data")));
    898898        }
    899899    }
  • /trunk/src/org/openstreetmap/josm/gui/layer/Layer.java

    r2024 r2060  
    4545
    4646    /** keeps track of property change listeners */
    47     private PropertyChangeSupport propertyChangeSupport;
     47    protected PropertyChangeSupport propertyChangeSupport;
    4848
    4949    /**
  • /trunk/src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java

    r2024 r2060  
    7171 */
    7272public class OsmDataLayer extends Layer {
     73    static public final String REQUIRES_SAVE_TO_DISK_PROP = OsmDataLayer.class.getName() + ".requiresSaveToDisk";
     74    static public final String REQUIRES_UPLOAD_TO_SERVER_PROP = OsmDataLayer.class.getName() + ".requiresUploadToServer";
     75
     76    private boolean requiresSaveToFile = false;
     77    private boolean requiresUploadToServer = false;
     78
     79    protected void setRequiresSaveToFile(boolean newValue) {
     80        boolean oldValue = requiresSaveToFile;
     81        requiresSaveToFile = newValue;
     82        if (oldValue != newValue) {
     83            propertyChangeSupport.firePropertyChange(REQUIRES_SAVE_TO_DISK_PROP, oldValue, newValue);
     84        }
     85    }
     86
     87    protected void setRequiresUploadToServer(boolean newValue) {
     88        boolean oldValue = requiresUploadToServer;
     89        requiresUploadToServer = newValue;
     90        if (oldValue != newValue) {
     91            propertyChangeSupport.firePropertyChange(REQUIRES_UPLOAD_TO_SERVER_PROP, oldValue, newValue);
     92        }
     93    }
    7394
    7495    /** the global counter for created data layers */
     
    96117        private void inc(final OsmPrimitive osm, final int i) {
    97118            normal[i]++;
    98             if (osm.deleted) {
     119            if (osm.isDeleted()) {
    99120                deleted[i]++;
    100121            }
     
    113134    }
    114135
    115     public interface ModifiedChangedListener {
    116         void modifiedChanged(boolean value, OsmDataLayer source);
    117     }
    118136    public interface CommandQueueListener {
    119137        void commandChanged(int queueSize, int redoSize);
     
    130148    private ConflictCollection conflicts;
    131149
    132     /**
    133      * Whether the data of this layer was modified during the session.
    134      */
    135     private boolean modified = false;
    136     /**
    137      * Whether the data was modified due an upload of the data to the server.
    138      */
    139     public boolean uploadedModified = false;
    140 
    141     public final LinkedList<ModifiedChangedListener> listenerModified = new LinkedList<ModifiedChangedListener>();
    142150    public final LinkedList<DataChangeListener> listenerDataChanged = new LinkedList<DataChangeListener>();
    143151
     
    310318    @Override public void visitBoundingBox(final BoundingXYVisitor v) {
    311319        for (final Node n : data.nodes)
    312             if (!n.deleted && !n.incomplete) {
     320            if (!n.isDeleted() && !n.incomplete) {
    313321                v.visit(n);
    314322            }
    315     }
    316 
    317     /**
    318      * Cleanup the layer after save to disk. Just marks the layer as unmodified.
    319      * Leaves the undo/redo stack unchanged.
    320      *
    321      */
    322     public void cleanupAfterSaveToDisk() {
    323         setModified(false);
    324323    }
    325324
     
    333332     */
    334333    public void cleanupAfterUpload(final Collection<OsmPrimitive> processed) {
    335 
    336334        // return immediately if an upload attempt failed
    337335        if (processed == null || processed.isEmpty())
     
    351349            cleanIterator(it, processedSet);
    352350        }
    353 
    354         setModified(true);
    355351    }
    356352
     
    367363        if (!processed.remove(osm))
    368364            return;
    369         osm.modified = false;
    370         if (osm.deleted) {
     365        osm.setModified(false);
     366        if (osm.isDeleted()) {
    371367            it.remove();
    372         }
    373     }
    374 
    375     public boolean isModified() {
    376         return modified;
    377     }
    378 
    379     public void setModified(final boolean modified) {
    380         if (modified == this.modified)
    381             return;
    382         this.modified = modified;
    383         for (final ModifiedChangedListener l : listenerModified) {
    384             l.modifiedChanged(modified, this);
    385368        }
    386369    }
     
    392375        int size = 0;
    393376        for (final OsmPrimitive osm : list)
    394             if (!osm.deleted) {
     377            if (!osm.isDeleted()) {
    395378                size++;
    396379            }
     
    446429
    447430    public void fireDataChange() {
     431        setRequiresSaveToFile(true);
     432        setRequiresUploadToServer(true);
    448433        for (DataChangeListener dcl : listenerDataChanged) {
    449434            dcl.dataChanged(this);
     
    456441        HashSet<Node> doneNodes = new HashSet<Node>();
    457442        for (Way w : data.ways) {
    458             if (w.incomplete || w.deleted) {
     443            if (w.incomplete || w.isDeleted()) {
    459444                continue;
    460445            }
     
    468453            ArrayList<WayPoint> trkseg = null;
    469454            for (Node n : w.getNodes()) {
    470                 if (n.incomplete || n.deleted) {
     455                if (n.incomplete || n.isDeleted()) {
    471456                    trkseg = null;
    472457                    continue;
     
    492477        // records them?
    493478        for (Node n : data.nodes) {
    494             if (n.incomplete || n.deleted || doneNodes.contains(n)) {
     479            if (n.incomplete || n.isDeleted() || doneNodes.contains(n)) {
    495480                continue;
    496481            }
     
    546531        return conflicts;
    547532    }
     533
     534    /**
     535     * Replies true if the data managed by this layer needs to be uploaded to
     536     * the server because it contains at least one modified primitive.
     537     *
     538     * @return true if the data managed by this layer needs to be uploaded to
     539     * the server because it contains at least one modified primitive; false,
     540     * otherwise
     541     */
     542    public boolean requiresUploadToServer() {
     543        return requiresUploadToServer;
     544    }
     545
     546    /**
     547     * Replies true if the data managed by this layer needs to be saved to
     548     * a file. Only replies true if a file is assigned to this layer and
     549     * if the data managed by this layer has been modified since the last
     550     * save operation to the file.
     551     *
     552     * @return true if the data managed by this layer needs to be saved to
     553     * a file
     554     */
     555    public boolean requiresSaveToFile() {
     556        return getAssociatedFile() != null && requiresSaveToFile;
     557    }
     558
     559    /**
     560     * Initializes the layer after a successful load of OSM data from a file
     561     *
     562     */
     563    public void onPostLoadFromFile() {
     564        setRequiresSaveToFile(false);
     565        setRequiresUploadToServer(data.isModified());
     566    }
     567
     568    /**
     569     * Initializes the layer after a successful save of OSM data to a file
     570     *
     571     */
     572    public void onPostSaveToFile() {
     573        setRequiresSaveToFile(false);
     574        setRequiresUploadToServer(data.isModified());
     575    }
     576
     577    /**
     578     * Initializes the layer after a successful upload to the server
     579     *
     580     */
     581    public void onPostUploadToServer() {
     582        setRequiresUploadToServer(false);
     583        // keep requiresSaveToDisk unchanged
     584    }
    548585}
  • /trunk/src/org/openstreetmap/josm/gui/preferences/PreferenceDialog.java

    r2024 r2060  
    77import java.awt.GridBagLayout;
    88import java.awt.ScrollPane;
     9import java.awt.event.MouseWheelEvent;
     10import java.awt.event.MouseWheelListener;
    911import java.util.ArrayList;
    1012import java.util.Collection;
     
    3335 * @author imi
    3436 */
    35 public class PreferenceDialog extends JTabbedPane {
     37public class PreferenceDialog extends JTabbedPane implements MouseWheelListener {
    3638
    3739    private final static Collection<PreferenceSettingFactory> settingsFactory = new LinkedList<PreferenceSettingFactory>();
     
    116118    public PreferenceDialog() {
    117119        super(JTabbedPane.LEFT, JTabbedPane.SCROLL_TAB_LAYOUT);
     120
     121        super.addMouseWheelListener(this);
    118122
    119123        for (PreferenceSettingFactory factory:settingsFactory) {
     
    174178        settingsFactory.add(new AdvancedPreference.Factory());
    175179    }
     180
     181    /**
     182     * This mouse wheel listener reacts when a scroll is carried out over the
     183     * tab strip and scrolls one tab/down or up, selecting it immediately.
     184     */
     185    public void mouseWheelMoved(MouseWheelEvent wev) {
     186        // Ensure the cursor is over the tab strip
     187        if(super.indexAtLocation(wev.getPoint().x, wev.getPoint().y) < 0)
     188            return;
     189
     190        // Get currently selected tab
     191        int newTab = super.getSelectedIndex() + wev.getWheelRotation();
     192
     193        // Ensure the new tab index is sound
     194        newTab = newTab < 0 ? 0 : newTab;
     195        newTab = newTab >= super.getTabCount() ? super.getTabCount() - 1 : newTab;
     196
     197        // select new tab
     198        super.setSelectedIndex(newTab);
     199    }
    176200}
  • /trunk/src/org/openstreetmap/josm/gui/progress/PleaseWaitProgressMonitor.java

    r2024 r2060  
    2828
    2929    private PleaseWaitDialog dialog;
     30    private String windowTitle;
    3031
    3132    public PleaseWaitProgressMonitor() {
     33        this("");
     34    }
     35
     36    public PleaseWaitProgressMonitor(String windowTitle) {
    3237        this(JOptionPane.getFrameForComponent(Main.map));
     38        this.windowTitle = windowTitle;
    3339    }
    3440
     
    8692                    throw new ProgressException("PleaseWaitDialog parent must be either Frame or Dialog");
    8793
     94                if (windowTitle != null) {
     95                    dialog.setTitle(windowTitle);
     96                }
    8897                dialog.cancel.setEnabled(true);
    8998                dialog.setCustomText("");
  • /trunk/src/org/openstreetmap/josm/gui/tagging/TaggingPreset.java

    r2024 r2060  
    1818import java.util.Collection;
    1919import java.util.HashMap;
    20 import java.util.HashSet;
    2120import java.util.LinkedHashMap;
    2221import java.util.LinkedList;
    2322import java.util.List;
    24 import java.util.Set;
     23import java.util.TreeSet;
    2524
    2625import javax.swing.AbstractAction;
     
    4544import org.openstreetmap.josm.gui.ExtendedDialog;
    4645import org.openstreetmap.josm.gui.QuadStateCheckBox;
     46import org.openstreetmap.josm.gui.layer.OsmDataLayer;
     47import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionCache;
     48import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionItemPritority;
     49import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionList;
    4750import org.openstreetmap.josm.io.MirroredInputStream;
    4851import org.openstreetmap.josm.tools.GBC;
     
    6568    public String locale_name;
    6669
     70    private static AutoCompletionList autoCompletionList;
     71
     72    public static AutoCompletionList getPresetAutocompletionList() {
     73        if (autoCompletionList == null) {
     74            autoCompletionList = new AutoCompletionList();
     75        }
     76        return autoCompletionList;
     77    }
     78
    6779    public static abstract class Item {
     80        protected void initAutoCompletionField(AutoCompletingTextField field, String key) {
     81            OsmDataLayer layer = Main.main.getEditLayer();
     82            if (layer == null) return;
     83            field.setAutoCompletionList(getPresetAutocompletionList());
     84        }
     85
    6886        public boolean focus = false;
    6987        abstract boolean addToPanel(JPanel p, Collection<OsmPrimitive> sel);
     
    7391
    7492    public static class Usage {
    75         Set<String> values;
    76         Boolean hadKeys = false;
    77         Boolean hadEmpty = false;
    78         public Boolean allSimilar()
    79         {
     93        TreeSet<String> values;
     94        boolean hadKeys = false;
     95        boolean hadEmpty = false;
     96        public boolean hasUniqueValue() {
    8097            return values.size() == 1 && !hadEmpty;
    8198        }
    82         public Boolean unused()
    83         {
     99
     100        public boolean unused() {
    84101            return values.size() == 0;
    85102        }
    86         public String getFirst()
    87         {
    88             return (String)(values.toArray()[0]);
    89         }
    90         public Boolean hadKeys()
    91         {
     103        public String getFirst() {
     104            return values.first();
     105        }
     106
     107        public boolean hadKeys() {
    92108            return hadKeys;
    93109        }
     
    98114    static Usage determineTextUsage(Collection<OsmPrimitive> sel, String key) {
    99115        Usage returnValue = new Usage();
    100         returnValue.values = new HashSet<String>();
     116        returnValue.values = new TreeSet<String>();
    101117        for (OsmPrimitive s : sel) {
    102118            String v = s.get(key);
     
    106122                returnValue.hadEmpty = true;
    107123            }
    108             returnValue.hadKeys = returnValue.hadKeys | s.hasKeys();
     124            returnValue.hadKeys = ! returnValue.values.isEmpty() | returnValue.hadEmpty;
    109125        }
    110126        return returnValue;
     
    114130
    115131        Usage returnValue = new Usage();
    116         returnValue.values = new HashSet<String>();
     132        returnValue.values = new TreeSet<String>();
    117133        for (OsmPrimitive s : sel) {
    118134            returnValue.values.add(OsmUtils.getNamedOsmBoolean(s.get(key)));
     
    133149        private JComponent value;
    134150
     151
    135152        @Override public boolean addToPanel(JPanel p, Collection<OsmPrimitive> sel) {
    136153
    137154            // find out if our key is already used in the selection.
    138155            Usage usage = determineTextUsage(sel, key);
    139             if (usage.unused())
    140             {
    141                 value = new JTextField();
     156            if (usage.unused()){
     157                AutoCompletingTextField textField = new AutoCompletingTextField();
     158                initAutoCompletionField(textField, key);
    142159                if (use_last_as_default && lastValue.containsKey(key)) {
    143                     ((JTextField)value).setText(lastValue.get(key));
     160                    textField.setText(lastValue.get(key));
    144161                } else {
    145                     ((JTextField)value).setText(default_);
    146                 }
     162                    textField.setText(default_);
     163                }
     164                value = textField;
    147165                originalValue = null;
    148             } else if (usage.allSimilar()) {
     166            } else if (usage.hasUniqueValue()) {
    149167                // all objects use the same value
    150                 value = new JTextField();
    151                 for (String s : usage.values) {
    152                     ((JTextField) value).setText(s);
    153                 }
    154                 originalValue = ((JTextField)value).getText();
     168                AutoCompletingTextField textField = new AutoCompletingTextField();
     169                initAutoCompletionField(textField, key);
     170                textField.setText(usage.getFirst());
     171                value = textField;
     172                originalValue = usage.getFirst();
    155173            } else {
    156174                // the objects have different values
    157                 value = new JComboBox(usage.values.toArray());
    158                 ((JComboBox)value).setEditable(true);
    159                 ((JComboBox)value).getEditor().setItem(DIFFERENT);
     175                AutoCompletingTextField textField = new AutoCompletingTextField();
     176                initAutoCompletionField(textField, key);
     177                JComboBox comboBox = new JComboBox(usage.values.toArray());
     178                comboBox.setEditable(true);
     179                comboBox.setEditor(textField);
     180                comboBox.getEditor().setItem(DIFFERENT);
     181                value=comboBox;
    160182                originalValue = DIFFERENT;
    161183            }
     
    300322
    301323            lhm = new LinkedHashMap<String,String>();
    302             if (!usage.allSimilar() && !usage.unused())
    303             {
     324            if (!usage.hasUniqueValue() && !usage.unused()){
    304325                lhm.put(DIFFERENT, DIFFERENT);
    305326            }
     
    309330                                tr(display_array[i]) : display_array[i]);
    310331            }
    311             if(!usage.unused())
    312             {
     332            if(!usage.unused()){
    313333                for (String s : usage.values) {
    314334                    if (!lhm.containsKey(s)) {
     
    326346            combo = new JComboBox(lhm.values().toArray());
    327347            combo.setEditable(editable);
    328             if (usage.allSimilar() && !usage.unused())
    329             {
     348            AutoCompletingTextField tf = new AutoCompletingTextField();
     349            initAutoCompletionField(tf, key);
     350            tf.getAutoCompletionList().add(Arrays.asList(display_array), AutoCompletionItemPritority.IS_IN_STANDARD);
     351            combo.setEditor(tf);
     352
     353            if (usage.hasUniqueValue() && !usage.unused()){
    330354                originalValue=usage.getFirst();
    331355                combo.setSelectedItem(lhm.get(originalValue));
    332356            }
    333357            // use default only in case it is a totally new entry
    334             else if(default_ != null && !usage.hadKeys())
    335             {
     358            else if(default_ != null && !usage.hadKeys()) {
    336359                combo.setSelectedItem(default_);
    337360                originalValue=DIFFERENT;
    338361            }
    339             else if(usage.unused())
    340             {
     362            else if(usage.unused()){
    341363                combo.setSelectedItem("");
    342364                originalValue="";
    343365            }
    344             else
    345             {
     366            else{
    346367                combo.setSelectedItem(DIFFERENT);
    347368                originalValue=DIFFERENT;
     
    625646    }
    626647
     648    protected void refreshAutocompletionList(final OsmDataLayer layer) {
     649        Runnable task = new Runnable() {
     650            public void run() {
     651                System.out.print("refreshing preset auto completion list ...");
     652                AutoCompletionCache.getCacheForLayer(layer).initFromDataSet();
     653                AutoCompletionCache.getCacheForLayer(layer).populateWithValues( getPresetAutocompletionList(), false /* don't append */);
     654                System.out.println("DONE");
     655            }
     656        };
     657        new Thread(task).run();
     658
     659    }
    627660    public PresetPanel createPanel(Collection<OsmPrimitive> selected) {
    628661        if (data == null)
    629662            return null;
     663        OsmDataLayer layer = Main.main.getEditLayer();
     664        if (layer != null) {
     665            refreshAutocompletionList(layer);
     666        }
    630667        PresetPanel p = new PresetPanel();
    631668        LinkedList<Item> l = new LinkedList<Item>();
    632         if(types != null)
    633         {
     669        if(types != null){
    634670            JPanel pp = new JPanel();
    635             for(String t : types)
    636             {
     671            for(String t : types){
    637672                JLabel la = new JLabel(ImageProvider.get("Mf_" + t));
    638673                la.setToolTipText(tr("Elements of type {0} are supported.", tr(t)));
     
    642677        }
    643678
    644         for (Item i : data)
    645         {
     679        for (Item i : data){
    646680            if(i instanceof Link) {
    647681                l.add(i);
    648             } else
    649             {
     682            } else {
    650683                if(i.addToPanel(p, selected)) {
    651684                    p.hasElements = true;
     
    683716                            true);
    684717                    contentConstraints = GBC.eol().fill().insets(5,10,5,0);
    685                     setupDialog(content, new String[] {"ok.png", "cancel.png" });
     718                    setButtonIcons(new String[] {"ok.png", "cancel.png" });
     719                    setContent(content);
     720                    setupDialog();
    686721                    buttons.get(0).setEnabled(!disableApply);
    687722                    buttons.get(0).setToolTipText(title);
  • /trunk/src/org/openstreetmap/josm/io/DiffResultReader.java

    r2024 r2060  
    9393
    9494    public void visit(Node n) {
    95         String key = "node:" + (newIdMap.containsKey(n) ? newIdMap.get(n) : n.id);
     95        String key = "node:" + (newIdMap.containsKey(n) ? newIdMap.get(n) : n.getId());
    9696        System.out.println("key: "+key);
    9797        Long[] nv = versions.get(key);
    9898        if (nv != null) {
    9999            processed.add(n);
    100             if (!n.deleted) {
     100            if (!n.isDeleted()) {
    101101                n.id = nv[0]; n.version = nv[1].intValue();
    102102            }
     
    104104    }
    105105    public void visit(Way w) {
    106         String key = "way:" + (newIdMap.containsKey(w) ? newIdMap.get(w) : w.id);
     106        String key = "way:" + (newIdMap.containsKey(w) ? newIdMap.get(w) : w.getId());
    107107        Long[] nv = versions.get(key);
    108108        if (nv != null) {
    109109            processed.add(w);
    110             if (!w.deleted) {
     110            if (!w.isDeleted()) {
    111111                w.id = nv[0]; w.version = nv[1].intValue();
    112112            }
     
    114114    }
    115115    public void visit(Relation r) {
    116         String key = "relation:" + (newIdMap.containsKey(r) ? newIdMap.get(r) : r.id);
     116        String key = "relation:" + (newIdMap.containsKey(r) ? newIdMap.get(r) : r.getId());
    117117        Long[] nv = versions.get(key);
    118118        if (nv != null) {
    119119            processed.add(r);
    120             if (!r.deleted) {
     120            if (!r.isDeleted()) {
    121121                r.id = nv[0]; r.version = nv[1].intValue();
    122122            }
  • /trunk/src/org/openstreetmap/josm/io/GpxExporter.java

    r2024 r2060  
    112112        p.add(keywords, GBC.eop().fill(GBC.HORIZONTAL));
    113113
    114         int answer = new ExtendedDialog(Main.parent, tr("Export options"), p, new String[] { tr("Export and Save"),
    115             tr("Cancel") }, new String[] { "exportgpx.png", "cancel.png" }).getValue();
    116         if (answer != 1)
     114        ExtendedDialog ed = new ExtendedDialog(Main.parent,
     115                tr("Export options"),
     116                new String[] { tr("Export and Save"), tr("Cancel") });
     117        ed.setButtonIcons(new String[] { "exportgpx.png", "cancel.png" });
     118        ed.setContent(p);
     119        ed.showDialog();
     120
     121        if (ed.getValue() != 1)
    117122            return;
    118123
  • /trunk/src/org/openstreetmap/josm/io/MultiFetchServerObjectReader.java

    r2024 r2060  
    168168    public MultiFetchServerObjectReader append(Node node) {
    169169        if (node == null) return this;
    170         if (node.id == 0) return this;
    171         remember(node.id, OsmPrimitiveType.NODE);
     170        if (node.getId() == 0) return this;
     171        remember(node.getId(), OsmPrimitiveType.NODE);
    172172        return this;
    173173    }
     
    182182    public MultiFetchServerObjectReader append(Way way) {
    183183        if (way == null) return this;
    184         if (way.id == 0) return this;
     184        if (way.getId() == 0) return this;
    185185        for (Node node: way.getNodes()) {
    186             if (node.id > 0) {
    187                 remember(node.id, OsmPrimitiveType.NODE);
    188             }
    189         }
    190         remember(way.id, OsmPrimitiveType.WAY);
     186            if (node.getId() > 0) {
     187                remember(node.getId(), OsmPrimitiveType.NODE);
     188            }
     189        }
     190        remember(way.getId(), OsmPrimitiveType.WAY);
    191191        return this;
    192192    }
     
    201201    public MultiFetchServerObjectReader append(Relation relation) {
    202202        if (relation == null) return this;
    203         if (relation.id == 0) return this;
    204         remember(relation.id, OsmPrimitiveType.RELATION);
     203        if (relation.getId() == 0) return this;
     204        remember(relation.getId(), OsmPrimitiveType.RELATION);
    205205        for (RelationMember member : relation.getMembers()) {
    206206            if (OsmPrimitiveType.from(member.member).equals(OsmPrimitiveType.RELATION)) {
    207207                // avoid infinite recursion in case of cyclic dependencies in relations
    208208                //
    209                 if (relations.contains(member.member.id)) {
     209                if (relations.contains(member.member.getId())) {
    210210                    continue;
    211211                }
     
    373373                String msg = "";
    374374                switch(type) {
    375                 case NODE: msg = tr("Fetching node with id {0} from ''{1}''", id, OsmApi.getOsmApi().getBaseUrl()); break;
    376                 case WAY: msg = tr("Fetching way with id {0} from ''{1}''", id, OsmApi.getOsmApi().getBaseUrl()); break;
    377                 case RELATION: msg = tr("Fetching relation with id {0} from ''{1}''", id, OsmApi.getOsmApi().getBaseUrl()); break;
     375                    case NODE: msg = tr("Fetching node with id {0} from ''{1}''", id, OsmApi.getOsmApi().getBaseUrl()); break;
     376                    case WAY: msg = tr("Fetching way with id {0} from ''{1}''", id, OsmApi.getOsmApi().getBaseUrl()); break;
     377                    case RELATION: msg = tr("Fetching relation with id {0} from ''{1}''", id, OsmApi.getOsmApi().getBaseUrl()); break;
    378378                }
    379379                progressMonitor.setCustomText(msg);
     
    411411        String msg = "";
    412412        switch(type) {
    413         case NODE: msg = tr("Fetching a package of nodes from ''{0}''", OsmApi.getOsmApi().getBaseUrl()); break;
    414         case WAY:  msg = tr("Fetching a package of ways from ''{0}''", OsmApi.getOsmApi().getBaseUrl()); break;
    415         case RELATION:  msg = tr("Fetching a package of relations from ''{0}''", OsmApi.getOsmApi().getBaseUrl()); break;
     413            case NODE: msg = tr("Fetching a package of nodes from ''{0}''", OsmApi.getOsmApi().getBaseUrl()); break;
     414            case WAY:  msg = tr("Fetching a package of ways from ''{0}''", OsmApi.getOsmApi().getBaseUrl()); break;
     415            case RELATION:  msg = tr("Fetching a package of relations from ''{0}''", OsmApi.getOsmApi().getBaseUrl()); break;
    416416        }
    417417        progressMonitor.setCustomText(msg);
  • /trunk/src/org/openstreetmap/josm/io/OsmApi.java

    r2024 r2060  
    145145
    146146    /**
    147      * Returns true if the negotiated version supports changesets.
    148      * @return true if the negotiated version supports changesets.
    149      */
    150     public boolean hasChangesetSupport() {
     147     * Returns true if the negotiated version supports diff uploads.
     148     * @return true if the negotiated version supports diff uploads
     149     */
     150    public boolean hasSupportForDiffUploads() {
    151151        return ((version != null) && (version.compareTo("0.6")>=0));
    152152    }
     
    157157     * @exception OsmApiInitializationException thrown, if an exception occurs
    158158     */
    159     public void initialize() throws OsmApiInitializationException {
     159    public void initialize(ProgressMonitor monitor) throws OsmApiInitializationException {
    160160        if (initialized)
    161161            return;
     162        cancel = false;
    162163        initAuthentication();
    163164        try {
    164             String s = sendRequest("GET", "capabilities", null);
     165            String s = sendRequest("GET", "capabilities", null,monitor);
    165166            InputSource inputSource = new InputSource(new StringReader(s));
    166167            SAXParserFactory.newInstance().newSAXParser().parse(inputSource, new CapabilitiesParser());
     
    227228     * @throws OsmTransferException if something goes wrong
    228229     */
    229     public void createPrimitive(OsmPrimitive osm) throws OsmTransferException {
    230         initialize();
     230    public void createPrimitive(OsmPrimitive osm, ProgressMonitor monitor) throws OsmTransferException {
     231        initialize(monitor);
    231232        String ret = "";
    232233        try {
    233             ret = sendRequest("PUT", OsmPrimitiveType.from(osm).getAPIName()+"/create", toXml(osm, true));
     234            ret = sendRequest("PUT", OsmPrimitiveType.from(osm).getAPIName()+"/create", toXml(osm, true),monitor);
    234235            osm.id = Long.parseLong(ret.trim());
    235236            osm.version = 1;
     
    247248     * @throws OsmTransferException if something goes wrong
    248249     */
    249     public void modifyPrimitive(OsmPrimitive osm) throws OsmTransferException {
    250         initialize();
     250    public void modifyPrimitive(OsmPrimitive osm, ProgressMonitor monitor) throws OsmTransferException {
     251        initialize(monitor);
    251252        if (version.equals("0.5")) {
    252253            // legacy mode does not return the new object version.
    253             sendRequest("PUT", OsmPrimitiveType.from(osm).getAPIName()+"/" + osm.id, toXml(osm, true));
     254            sendRequest("PUT", OsmPrimitiveType.from(osm).getAPIName()+"/" + osm.getId(), toXml(osm, true),monitor);
    254255        } else {
    255256            String ret = null;
    256257            // normal mode (0.6 and up) returns new object version.
    257258            try {
    258                 ret = sendRequest("PUT", OsmPrimitiveType.from(osm).getAPIName()+"/" + osm.id, toXml(osm, true));
     259                ret = sendRequest("PUT", OsmPrimitiveType.from(osm).getAPIName()+"/" + osm.getId(), toXml(osm, true), monitor);
    259260                osm.version = Integer.parseInt(ret.trim());
    260261            } catch(NumberFormatException e) {
    261                 throw new OsmTransferException(tr("unexpected format of new version of modified primitive ''{0}'', got ''{1}''", osm.id, ret));
     262                throw new OsmTransferException(tr("unexpected format of new version of modified primitive ''{0}'', got ''{1}''", osm.getId(), ret));
    262263            }
    263264        }
     
    270271     */
    271272    public void deletePrimitive(OsmPrimitive osm, ProgressMonitor monitor) throws OsmTransferException {
    272         initialize();
     273        initialize(monitor);
    273274        // can't use a the individual DELETE method in the 0.6 API. Java doesn't allow
    274275        // submitting a DELETE request with content, the 0.6 API requires it, however. Falling back
     
    279280
    280281    /**
    281      * Creates a new changeset on the server to use for subsequent calls.
    282      * @param comment the "commit comment" for the new changeset
     282     * Creates the changeset to be used for subsequent uploads.
     283     *
     284     * If changesetProcessingType is {@see ChangesetProcessingType#USE_NEW} creates a new changeset based
     285     * on <code>changeset</code>. Otherwise uses the changeset given by {@see OsmApi#getCurrentChangeset()}.
     286     * If this changeset is null or has an id of value 0, a new changeset is created too.
     287     *
     288     * @param changeset the changeset to be used for uploading if <code>changesetProcessingType</code> is
     289     *   {@see ChangesetProcessingType#USE_NEW}
     290     * @param changesetProcessingType  how to handel changesets; set to {@see ChangesetProcessingType#USE_NEW} if null
     291     * @param progressMonitor the progress monitor
    283292     * @throws OsmTransferException signifying a non-200 return code, or connection errors
    284293     */
    285     public void createChangeset(String comment, ProgressMonitor progressMonitor) throws OsmTransferException {
    286         progressMonitor.beginTask((tr("Opening changeset...")));
     294    public void createChangeset(Changeset changeset, ChangesetProcessingType changesetProcessingType, ProgressMonitor progressMonitor) throws OsmTransferException {
     295        if (changesetProcessingType == null) {
     296            changesetProcessingType = ChangesetProcessingType.USE_NEW_AND_CLOSE;
     297        }
    287298        try {
    288             changeset = new Changeset();
    289             Properties sysProp = System.getProperties();
    290             Object ua = sysProp.get("http.agent");
    291             changeset.put("created_by", (ua == null) ? "JOSM" : ua.toString());
    292             changeset.put("comment", comment);
    293             createPrimitive(changeset);
     299            progressMonitor.beginTask((tr("Creating changeset...")));
     300            if (changesetProcessingType.isUseNew()) {
     301                Properties sysProp = System.getProperties();
     302                Object ua = sysProp.get("http.agent");
     303                changeset.put("created_by", (ua == null) ? "JOSM" : ua.toString());
     304                createPrimitive(changeset, progressMonitor);
     305                this.changeset = changeset;
     306                progressMonitor.setCustomText((tr("Successfully opened changeset {0}",changeset.getId())));
     307            } else {
     308                if (this.changeset == null || this.changeset.getId() == 0) {
     309                    progressMonitor.setCustomText((tr("No currently open changeset. Opening a new changeset...")));
     310                    System.out.println(tr("Warning: could not reuse an existing changeset as requested. Opening a new one."));
     311                    Properties sysProp = System.getProperties();
     312                    Object ua = sysProp.get("http.agent");
     313                    changeset.put("created_by", (ua == null) ? "JOSM" : ua.toString());
     314                    createPrimitive(changeset, progressMonitor);
     315                    this.changeset = changeset;
     316                    progressMonitor.setCustomText((tr("Successfully opened changeset {0}",this.changeset.getId())));
     317                } else {
     318                    progressMonitor.setCustomText((tr("Reusing existing changeset {0}", this.changeset.getId())));
     319                }
     320            }
    294321        } finally {
    295322            progressMonitor.finishTask();
     
    300327     * Closes a changeset on the server.
    301328     *
     329     * @param changesetProcessingType how changesets are currently handled
     330     * @param progressMonitor the progress monitor
     331     *
    302332     * @throws OsmTransferException if something goes wrong.
    303333     */
    304     public void stopChangeset(ProgressMonitor progressMonitor) throws OsmTransferException {
    305         progressMonitor.beginTask(tr("Closing changeset..."));
     334    public void stopChangeset(ChangesetProcessingType changesetProcessingType, ProgressMonitor progressMonitor) throws OsmTransferException {
     335        if (changesetProcessingType == null) {
     336            changesetProcessingType = ChangesetProcessingType.USE_NEW_AND_CLOSE;
     337        }
    306338        try {
    307             initialize();
    308             sendRequest("PUT", "changeset" + "/" + changeset.id + "/close", null);
    309             changeset = null;
     339            progressMonitor.beginTask(tr("Closing changeset..."));
     340            initialize(progressMonitor);
     341            if (changesetProcessingType.isCloseAfterUpload()) {
     342                progressMonitor.setCustomText(tr("Closing changeset {0}...", changeset.getId()));
     343                if (this.changeset != null && this.changeset.getId() > 0) {
     344                    sendRequest("PUT", "changeset" + "/" + changeset.getId() + "/close", null, progressMonitor);
     345                    changeset = null;
     346                }
     347            } else {
     348                progressMonitor.setCustomText(tr("Leaving changeset {0} open...", changeset.getId()));
     349            }
    310350        } finally {
    311351            progressMonitor.finishTask();
     
    327367                throw new OsmTransferException(tr("No changeset present for diff upload"));
    328368
    329             initialize();
     369            initialize(progressMonitor);
    330370            final ArrayList<OsmPrimitive> processed = new ArrayList<OsmPrimitive>();
    331371
     
    341381            String diff = duv.getDocument();
    342382            try {
    343                 String diffresult = sendRequest("POST", "changeset/" + changeset.id + "/upload", diff);
     383                String diffresult = sendRequest("POST", "changeset/" + changeset.getId() + "/upload", diff,progressMonitor);
    344384                DiffResultReader.parseDiffResult(diffresult, list, processed, duv.getNewIdMap(),
    345385                        progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false));
     
    358398
    359399
    360     private void sleepAndListen() throws OsmTransferCancelledException {
     400    private void sleepAndListen(int retry, ProgressMonitor monitor) throws OsmTransferCancelledException {
    361401        System.out.print(tr("Waiting 10 seconds ... "));
    362402        for(int i=0; i < 10; i++) {
     403            if (monitor != null) {
     404                monitor.setCustomText(tr("Starting retry {0} of {1} in {2} seconds ...", getMaxRetries() - retry,getMaxRetries(), 10-i));
     405            }
    363406            if (cancel || isAuthCancelled())
    364407                throw new OsmTransferCancelledException();
     
    395438     *    been exhausted), or rewrapping a Java exception.
    396439     */
    397     private String sendRequest(String requestMethod, String urlSuffix,
    398             String requestBody) throws OsmTransferException {
     440    private String sendRequest(String requestMethod, String urlSuffix,String requestBody, ProgressMonitor monitor) throws OsmTransferException {
    399441
    400442        StringBuffer responseBody = new StringBuffer();
     
    436478                if (retCode >= 500) {
    437479                    if (retries-- > 0) {
    438                         sleepAndListen();
    439                         int maxRetries = getMaxRetries();
    440                         System.out.println(tr("Starting retry {0} of {1}.", maxRetries - retries,maxRetries));
     480                        sleepAndListen(retries, monitor);
     481                        System.out.println(tr("Starting retry {0} of {1}.", getMaxRetries() - retries,getMaxRetries()));
    441482                        continue;
    442483                    }
  • /trunk/src/org/openstreetmap/josm/io/OsmConnection.java

    r2024 r2060  
    2323import org.openstreetmap.josm.Main;
    2424import org.openstreetmap.josm.gui.ExtendedDialog;
     25import org.openstreetmap.josm.gui.progress.ProgressMonitor;
    2526import org.openstreetmap.josm.tools.Base64;
    2627import org.openstreetmap.josm.tools.GBC;
     
    9495
    9596    public void cancel() {
    96         //TODO
    97         //Main.pleaseWaitDlg.currentAction.setText(tr("Aborting..."));
    9897        cancel = true;
    9998        if (activeConnection != null) {
     
    112111        try {
    113112            synchronized (credentialsManager) {
    114                 auth = credentialsManager.lookup(CredentialsManager.Key.USERNAME) + ":" + 
    115                     credentialsManager.lookup(CredentialsManager.Key.PASSWORD);
     113                auth = credentialsManager.lookup(CredentialsManager.Key.USERNAME) + ":" +
     114                credentialsManager.lookup(CredentialsManager.Key.PASSWORD);
    116115            }
    117116        } catch (CredentialsManager.CMException e) {
     
    139138            String secret = Main.pref.get("osm-server." + key.toString(), null);
    140139            if (secret == null) throw new CredentialsManager.NoContentException();
    141             return secret;           
     140            return secret;
    142141        }
    143142        public void store(CredentialsManager.Key key, String secret) {
     
    171170                p.add(warning, GBC.eop());
    172171
    173                 JCheckBox savePassword = new JCheckBox(tr("Save user and password (unencrypted)"), 
    174                                                        !username.equals("") && !password.equals(""));
     172                JCheckBox savePassword = new JCheckBox(tr("Save user and password (unencrypted)"),
     173                        !username.equals("") && !password.equals(""));
    175174                p.add(savePassword, GBC.eop());
    176175
    177                 int choice = new ExtendedDialog(
    178                     Main.parent,
    179                     tr("Enter Password"),
    180                     p,
    181                     new String[] {tr("Login"), tr("Cancel")},
    182                     new String[] {"ok.png", "cancel.png"}).getValue();
    183 
    184                 if (choice != 1) {
     176                ExtendedDialog dialog = new ExtendedDialog(
     177                        Main.parent,
     178                        tr("Enter Password"),
     179                        new String[] {tr("Login"), tr("Cancel")}
     180                );
     181                dialog.setContent(p);
     182                dialog.setButtonIcons( new String[] {"ok.png", "cancel.png"});
     183                dialog.showDialog();
     184
     185                if (dialog.getValue() != 1) {
    185186                    caller.authCancelled = true;
    186187                    return null;
     
    223224                        oldServerURL = "";
    224225                    }
    225                     if (oldServerURL.equals("")) oldServerURL = "http://api.openstreetmap.org/api";
     226                    if (oldServerURL.equals("")) {
     227                        oldServerURL = "http://api.openstreetmap.org/api";
     228                    }
    226229                    try {
    227230                        oldUsername = lookup(Key.USERNAME);
     
    258261                    String newPassword = String.valueOf(osmDataPassword.getPassword());
    259262                    if (!oldServerURL.equals(newServerURL)) {
    260                         store(Key.OSM_SERVER_URL, newServerURL); 
     263                        store(Key.OSM_SERVER_URL, newServerURL);
    261264                    }
    262265                    if (!oldUsername.equals(newUsername)) {
  • /trunk/src/org/openstreetmap/josm/io/OsmExporter.java

    r2024 r2060  
    7676                tmpFile.delete();
    7777            }
    78             layer.cleanupAfterSaveToDisk();
     78            layer.onPostSaveToFile();
    7979        } catch (IOException e) {
    8080            e.printStackTrace();
  • /trunk/src/org/openstreetmap/josm/io/OsmImporter.java

    r2024 r2060  
    1010import java.io.IOException;
    1111import java.io.InputStream;
     12
     13import javax.swing.SwingUtilities;
    1214
    1315import org.openstreetmap.josm.Main;
     
    4749        OsmReader osm = OsmReader.parseDataSetOsm(in, NullProgressMonitor.INSTANCE);
    4850        DataSet dataSet = osm.getDs();
    49         OsmDataLayer layer = new OsmDataLayer(dataSet, associatedFile.getName(), associatedFile);
    50         Main.main.addLayer(layer);
    51         layer.fireDataChange();
     51        final OsmDataLayer layer = new OsmDataLayer(dataSet, associatedFile.getName(), associatedFile);
     52        // FIXME: remove UI stuff from IO subsystem
     53        //
     54        Runnable uiStuff = new Runnable() {
     55            public void run() {
     56                Main.main.addLayer(layer);
     57                layer.fireDataChange();
     58                layer.onPostLoadFromFile();
     59            }
     60        };
     61        if (SwingUtilities.isEventDispatchThread()) {
     62            uiStuff.run();
     63        } else {
     64            SwingUtilities.invokeLater(uiStuff);
     65        }
    5266    }
    5367}
  • /trunk/src/org/openstreetmap/josm/io/OsmServerReader.java

    r2024 r2060  
    4040    protected InputStream getInputStream(String urlStr, ProgressMonitor progressMonitor) throws OsmTransferException  {
    4141        try {
    42             api.initialize();
     42            api.initialize(progressMonitor);
    4343            urlStr = api.getBaseUrl() + urlStr;
    4444            return getInputStreamRaw(urlStr, progressMonitor);
  • /trunk/src/org/openstreetmap/josm/io/OsmServerWriter.java

    r2024 r2060  
    8282     *
    8383     * @param primitives the collection of primitives to upload
     84     * @param changeset the changeset to be used if <code>changesetProcessingType</code> indicates that
     85     *   a new changeset should be opened
     86     * @param changesetProcessingType how we handle changesets
    8487     * @param progressMonitor the progress monitor
    8588     * @throws OsmTransferException thrown if an exception occurs
    8689     */
    87     protected void uploadChangesIndividually(Collection<OsmPrimitive> primitives, ProgressMonitor progressMonitor) throws OsmTransferException {
     90    protected void uploadChangesIndividually(Collection<OsmPrimitive> primitives, Changeset changeset, ChangesetProcessingType changesetProcessingType, ProgressMonitor progressMonitor) throws OsmTransferException {
    8891        try {
    8992            progressMonitor.setTicksCount(primitives.size());
    90             api.createChangeset(getChangesetComment(), progressMonitor.createSubTaskMonitor(0, false));
     93            api.createChangeset(changeset, changesetProcessingType,progressMonitor.createSubTaskMonitor(0, false));
    9194            uploadStartTime = System.currentTimeMillis();
    9295            for (OsmPrimitive osm : primitives) {
     
    9598                String msg = "";
    9699                switch(OsmPrimitiveType.from(osm)) {
    97                 case NODE: msg = marktr("{0}% ({1}/{2}), {3} left. Uploading node ''{4}'' (id: {5})"); break;
    98                 case WAY: msg = marktr("{0}% ({1}/{2}), {3} left. Uploading way ''{4}'' (id: {5})"); break;
    99                 case RELATION: msg = marktr("{0}% ({1}/{2}), {3} left. Uploading relation ''{4}'' (id: {5})"); break;
     100                    case NODE: msg = marktr("{0}% ({1}/{2}), {3} left. Uploading node ''{4}'' (id: {5})"); break;
     101                    case WAY: msg = marktr("{0}% ({1}/{2}), {3} left. Uploading way ''{4}'' (id: {5})"); break;
     102                    case RELATION: msg = marktr("{0}% ({1}/{2}), {3} left. Uploading relation ''{4}'' (id: {5})"); break;
    100103                }
    101104                progressMonitor.subTask(
     
    105108                                primitives.size(),
    106109                                time_left_str,
    107                                 osm.getName() == null ? osm.id : osm.getName(),
    108                                         osm.id));
     110                                osm.getName() == null ? osm.getId() : osm.getName(),
     111                                        osm.getId()));
    109112                makeApiRequest(osm,progressMonitor);
    110113                processed.add(osm);
     
    117120        } finally {
    118121            try {
    119                 api.stopChangeset(progressMonitor.createSubTaskMonitor(0, false));
     122                // starting the changeset may have failed, for instance because the user
     123                // cancelled the upload task. Only close the changeset if we currently have
     124                // an open changeset
     125
     126                if (api.getCurrentChangeset() != null && api.getCurrentChangeset().getId() > 0) {
     127                    api.stopChangeset(changesetProcessingType, progressMonitor.createSubTaskMonitor(0, false));
     128                }
    120129            } catch(Exception e) {
    121                 Changeset changeset = api.getCurrentChangeset();
    122                 String changesetId = (changeset == null ? tr("unknown") : Long.toString(changeset.id));
    123                 logger.warning(tr("Failed to close changeset {0}, will be closed by server after timeout. Exception was: {1}",
    124                         changesetId, e.toString()));
     130                OsmChangesetCloseException closeException = new OsmChangesetCloseException(e);
     131                closeException.setChangeset(api.getCurrentChangeset());
     132                throw closeException;
    125133            }
    126134        }
     
    134142     * @throws OsmTransferException thrown if an exception occurs
    135143     */
    136     protected void uploadChangesAsDiffUpload(Collection<OsmPrimitive> primitives, ProgressMonitor progressMonitor) throws OsmTransferException {
     144    protected void uploadChangesAsDiffUpload(Collection<OsmPrimitive> primitives, Changeset changeset, ChangesetProcessingType changesetProcessingType, ProgressMonitor progressMonitor) throws OsmTransferException {
    137145        // upload everything in one changeset
    138146        //
    139147        try {
    140             api.createChangeset(getChangesetComment(), progressMonitor.createSubTaskMonitor(0, false));
     148            api.createChangeset(changeset, changesetProcessingType, progressMonitor.createSubTaskMonitor(0, false));
    141149            processed.addAll(api.uploadDiff(primitives, progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false)));
    142150        } catch(OsmTransferException e) {
     
    146154        } finally {
    147155            try {
    148                 api.stopChangeset(progressMonitor.createSubTaskMonitor(0, false));
     156                api.stopChangeset(changesetProcessingType, progressMonitor.createSubTaskMonitor(0, false));
    149157            } catch (Exception ee) {
    150                 Changeset changeset = api.getCurrentChangeset();
    151                 String changesetId = (changeset == null ? tr("unknown") : Long.toString(changeset.id));
    152                 logger.warning(tr("Failed to close changeset {0}, will be closed by server after timeout. Exception was: {1}",
    153                         changesetId, ee.toString()));
     158                OsmChangesetCloseException closeException = new OsmChangesetCloseException(ee);
     159                closeException.setChangeset(api.getCurrentChangeset());
     160                throw closeException;
    154161            }
    155162        }
     
    162169     * @param primitives list of objects to send
    163170     */
    164     public void uploadOsm(String apiVersion, Collection<OsmPrimitive> primitives, ProgressMonitor progressMonitor) throws OsmTransferException {
     171    public void uploadOsm(String apiVersion, Collection<OsmPrimitive> primitives, Changeset changeset, ChangesetProcessingType changesetProcessingType, ProgressMonitor progressMonitor) throws OsmTransferException {
    165172        processed = new LinkedList<OsmPrimitive>();
    166173
    167         api.initialize();
    168 
    169         progressMonitor.beginTask("");
     174        api.initialize(progressMonitor);
    170175
    171176        try {
    172             // check whether we can use changeset
     177            // check whether we can use diff upload
    173178            //
    174             boolean canUseChangeset = api.hasChangesetSupport();
    175             boolean useChangeset = Main.pref.getBoolean("osm-server.atomic-upload", apiVersion.compareTo("0.6")>=0);
    176             if (useChangeset && ! canUseChangeset) {
    177                 System.out.println(tr("WARNING: preference ''{0}'' or api version ''{1}'' of dataset requires to use changesets, but API is not able to handle them. Ignoring changesets.", "osm-server.atomic-upload", apiVersion));
    178                 useChangeset = false;
    179             }
    180 
    181             if (useChangeset) {
    182                 uploadChangesAsDiffUpload(primitives, progressMonitor);
     179            boolean casUseDiffUploads = api.hasSupportForDiffUploads();
     180            boolean useDiffUpload = Main.pref.getBoolean("osm-server.atomic-upload", apiVersion.compareTo("0.6")>=0);
     181            if (useDiffUpload && ! casUseDiffUploads) {
     182                System.out.println(tr("WARNING: preference ''{0}'' or api version ''{1}'' of dataset requires to use diff uploads, but API is not able to handle them. Ignoring diff upload.", "osm-server.atomic-upload", apiVersion));
     183                useDiffUpload = false;
     184            }
     185
     186            if (useDiffUpload) {
     187                progressMonitor.beginTask(tr("Starting to upload in one request ..."));
     188                uploadChangesAsDiffUpload(primitives,changeset, changesetProcessingType, progressMonitor);
    183189            } else {
    184                 uploadChangesIndividually(primitives, progressMonitor);
     190                progressMonitor.beginTask(tr("Starting to upload with one request per primitive ..."));
     191                uploadChangesIndividually(primitives,changeset,changesetProcessingType,  progressMonitor);
    185192            }
    186193        } finally {
     
    190197
    191198    void makeApiRequest(OsmPrimitive osm, ProgressMonitor progressMonitor) throws OsmTransferException {
    192         if (osm.deleted) {
     199        if (osm.isDeleted()) {
    193200            api.deletePrimitive(osm, progressMonitor);
    194         } else if (osm.id == 0) {
    195             api.createPrimitive(osm);
     201        } else if (osm.getId() == 0) {
     202            api.createPrimitive(osm, progressMonitor);
    196203        } else {
    197             api.modifyPrimitive(osm);
    198         }
    199     }
    200 
    201     public void disconnectActiveConnection() {
    202         if (api != null && api.activeConnection != null) {
    203             api.activeConnection.disconnect();
     204            api.modifyPrimitive(osm,progressMonitor);
     205        }
     206    }
     207
     208    public void cancel() {
     209        if (api != null) {
     210            api.cancel();
    204211        }
    205212    }
  • /trunk/src/org/openstreetmap/josm/io/OsmWriter.java

    r2024 r2060  
    8585
    8686    private boolean shouldWrite(OsmPrimitive osm) {
    87         return osm.id != 0 || !osm.deleted;
     87        return osm.getId() != 0 || !osm.isDeleted();
    8888    }
    8989
     
    155155     */
    156156    private long getUsedId(OsmPrimitive osm) {
    157         if (osm.id != 0)
    158             return osm.id;
     157        if (osm.getId() != 0)
     158            return osm.getId();
    159159        if (usedNewIds.containsKey(osm))
    160160            return usedNewIds.get(osm);
     
    169169            }
    170170            for (Entry<String, String> e : osm.entrySet()) {
    171                 if ((osm instanceof Changeset) || !("created_by".equals(e.getKey())))
     171                if ((osm instanceof Changeset) || !("created_by".equals(e.getKey()))) {
    172172                    out.println("    <tag k='"+ XmlWriter.encode(e.getKey()) +
    173173                            "' v='"+XmlWriter.encode(e.getValue())+ "' />");
     174                }
    174175            }
    175176            out.println("  </" + tagname + ">");
     
    193194        if (!osmConform) {
    194195            String action = null;
    195             if (osm.deleted) {
     196            if (osm.isDeleted()) {
    196197                action = "delete";
    197             } else if (osm.modified) {
     198            } else if (osm.isModified()) {
    198199                action = "modify";
    199200            }
     
    209210            out.print(" user='"+XmlWriter.encode(osm.user.name)+"'");
    210211        }
    211         out.print(" visible='"+osm.visible+"'");
     212        out.print(" visible='"+osm.isVisible()+"'");
    212213        if (osm.version != -1) {
    213214            out.print(" version='"+osm.version+"'");
    214215        }
    215         if (this.changeset != null && this.changeset.id != 0) {
    216             out.print(" changeset='"+this.changeset.id+"'" );
     216        if (this.changeset != null && this.changeset.getId() != 0) {
     217            out.print(" changeset='"+this.changeset.getId()+"'" );
    217218        }
    218219    }
  • /trunk/src/org/openstreetmap/josm/plugins/PluginSelection.java

    r2024 r2060  
    9797            done = true;
    9898        } else {
    99             int answer = new ExtendedDialog(Main.parent,
     99            ExtendedDialog ed = new ExtendedDialog(Main.parent,
    100100                    tr("Update"),
    101                     tr("Update the following plugins:\n\n{0}", toUpdateStr.toString()),
    102                     new String[] {tr("Update Plugins"), tr("Cancel")},
    103                     new String[] {"dialogs/refresh.png", "cancel.png"}).getValue();
    104             if (answer == 1) {
     101                    new String[] {tr("Update Plugins"), tr("Cancel")});
     102            ed.setButtonIcons(new String[] {"dialogs/refresh.png", "cancel.png"});
     103            ed.setContent(tr("Update the following plugins:\n\n{0}", toUpdateStr.toString()));
     104            ed.showDialog();
     105
     106            if (ed.getValue() == 1) {
    105107                PluginDownloader.update(toUpdate);
    106108                done = true;
     
    133135        }
    134136        if (!toDownload.isEmpty()) {
    135             int answer = new ExtendedDialog(Main.parent,
     137            ExtendedDialog ed = new ExtendedDialog(Main.parent,
    136138                    tr("Download missing plugins"),
    137                     tr("Download the following plugins?\n\n{0}", msg),
    138                     new String[] {tr("Download Plugins"), tr("Cancel")},
    139                     new String[] {"download.png", "cancel.png"}).getValue();
     139                    new String[] {tr("Download Plugins"), tr("Cancel")});
     140            ed.setButtonIcons(new String[] {"download.png", "cancel.png"});
     141            ed.setContent(tr("Download the following plugins?\n\n{0}", msg));
     142            ed.showDialog();
     143
    140144            Collection<PluginInformation> error =
    141                 (answer != 1 ? toDownload : new PluginDownloader().download(toDownload));
     145                (ed.getValue() != 1 ? toDownload : new PluginDownloader().download(toDownload));
    142146            for (PluginInformation pd : error) {
    143147                pluginMap.put(pd.name, false);
  • /trunk/src/org/openstreetmap/josm/tools/PlatformHookOsx.java

    r2024 r2060  
    4848        //System.out.println("Going to handle method "+method+" (short: "+method.getName()+") with event "+args[0]);
    4949        if (method.getName().equals("handleQuit")) {
    50             handled = !Main.breakBecauseUnsavedChanges();
     50            handled = Main.saveUnsavedModifications();
    5151        } else if (method.getName().equals("handleAbout")) {
    5252            Main.main.menu.about.actionPerformed(null);
  • /trunk/test/functional/org/openstreetmap/josm/io/MultiFetchServerObjectReaderTest.java

    r2024 r2060  
    127127
    128128        OsmServerWriter writer = new OsmServerWriter();
    129         writer.uploadOsm("0.6", primitives, NullProgressMonitor.INSTANCE);
     129        writer.uploadOsm("0.6", primitives, null,null, NullProgressMonitor.INSTANCE);
    130130    }
    131131
  • /trunk/test/functional/org/openstreetmap/josm/io/OsmServerBackreferenceReaderTest.java

    r2024 r2060  
    129129        primitives.addAll(ds.relations);
    130130        OsmServerWriter writer = new OsmServerWriter();
    131         writer.uploadOsm("0.6", primitives, NullProgressMonitor.INSTANCE);
     131        writer.uploadOsm("0.6", primitives, null, null, NullProgressMonitor.INSTANCE);
    132132    }
    133133
Note: See TracChangeset for help on using the changeset viewer.