Changeset 14977 in josm


Ignore:
Timestamp:
2019-04-09T01:32:56+02:00 (8 months ago)
Author:
Don-vip
Message:

ensures consistency of upload comment:

  • fix #11168 - ctrl-z/undo could reset unwanted old changeset comment
  • fix #13474 - selecting "new changeset" after having entered a changeset comment did reset it to the previous value
  • fix #17452 - ctrl-enter while typing a changeset comment did upload with the previous value
  • fix behaviour of upload.comment.max-age: values were reset after 5 months instead of intended 4 hours because seconds were compared to milliseconds
  • avoid creation of unneeded undo/redo internal classes for non-editable text fields
  • ensures consistency of upload dialog if upload.comment properties are modified manually from advanced preferences
  • add a source attribute to preference events to know which class modified the preference entry
  • refactor reflection utils
Location:
trunk
Files:
1 added
27 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/data/Preferences.java

    r14153 r14977  
    1616import java.nio.file.InvalidPathException;
    1717import java.util.ArrayList;
     18import java.util.Arrays;
    1819import java.util.Collection;
    1920import java.util.Collections;
     
    4445import org.openstreetmap.josm.spi.preferences.AbstractPreferences;
    4546import org.openstreetmap.josm.spi.preferences.Config;
     47import org.openstreetmap.josm.spi.preferences.DefaultPreferenceChangeEvent;
    4648import org.openstreetmap.josm.spi.preferences.IBaseDirectories;
    4749import org.openstreetmap.josm.spi.preferences.ListSetting;
     50import org.openstreetmap.josm.spi.preferences.PreferenceChangeEvent;
    4851import org.openstreetmap.josm.spi.preferences.Setting;
    4952import org.openstreetmap.josm.tools.CheckParameterUtil;
     
    5154import org.openstreetmap.josm.tools.Logging;
    5255import org.openstreetmap.josm.tools.PlatformManager;
     56import org.openstreetmap.josm.tools.ReflectionUtils;
    5357import org.openstreetmap.josm.tools.Utils;
    5458import org.xml.sax.SAXException;
     
    120124
    121125    /**
     126     * Preferences classes calling directly the method {@link #putSetting(String, Setting)}.
     127     * This collection allows us to exclude them when searching the business class who set a preference.
     128     * The found class is used as event source when notifying event listeners.
     129     */
     130    private static final Collection<Class<?>> preferencesClasses = Arrays.asList(
     131            Preferences.class, PreferencesUtils.class, AbstractPreferences.class);
     132
     133    /**
    122134     * Constructs a new {@code Preferences}.
    123135     */
     
    216228
    217229    protected void firePreferenceChanged(String key, Setting<?> oldValue, Setting<?> newValue) {
    218         final org.openstreetmap.josm.spi.preferences.PreferenceChangeEvent evt =
    219                 new org.openstreetmap.josm.spi.preferences.DefaultPreferenceChangeEvent(key, oldValue, newValue);
     230        final PreferenceChangeEvent evt =
     231                new DefaultPreferenceChangeEvent(ReflectionUtils.findCallerClass(preferencesClasses), key, oldValue, newValue);
    220232        listeners.fireEvent(listener -> listener.preferenceChanged(evt));
    221233
  • trunk/src/org/openstreetmap/josm/data/StructUtils.java

    r13647 r14977  
    3333import org.openstreetmap.josm.tools.Logging;
    3434import org.openstreetmap.josm.tools.MultiMap;
    35 import org.openstreetmap.josm.tools.Utils;
     35import org.openstreetmap.josm.tools.ReflectionUtils;
    3636
    3737/**
     
    161161            }
    162162            try {
    163                 Utils.setObjectsAccessible(f);
     163                ReflectionUtils.setObjectsAccessible(f);
    164164                Object fieldValue = f.get(struct);
    165165                Object defaultFieldValue = f.get(structPrototype);
     
    215215                continue;
    216216            }
    217             Utils.setObjectsAccessible(f);
     217            ReflectionUtils.setObjectsAccessible(f);
    218218            if (f.getType() == Boolean.class || f.getType() == boolean.class) {
    219219                value = Boolean.valueOf(keyValue.getValue());
  • trunk/src/org/openstreetmap/josm/gui/MainApplication.java

    r14695 r14977  
    158158import org.openstreetmap.josm.tools.PlatformHookWindows;
    159159import org.openstreetmap.josm.tools.PlatformManager;
     160import org.openstreetmap.josm.tools.ReflectionUtils;
    160161import org.openstreetmap.josm.tools.Shortcut;
    161162import org.openstreetmap.josm.tools.Utils;
     
    991992            try {
    992993                Field field = Toolkit.class.getDeclaredField("resources");
    993                 Utils.setObjectsAccessible(field);
     994                ReflectionUtils.setObjectsAccessible(field);
    994995                field.set(null, ResourceBundle.getBundle("sun.awt.resources.awt"));
    995996            } catch (ReflectiveOperationException | RuntimeException e) { // NOPMD
  • trunk/src/org/openstreetmap/josm/gui/MapStatus.java

    r14379 r14977  
    253253            tr("The name of the object at the mouse pointer."),
    254254            getNameLabelCharacterCount(MainApplication.getMainFrame()), PROP_BACKGROUND_COLOR.get());
    255     private final JosmTextField helpText = new JosmTextField();
     255    private final JosmTextField helpText = new JosmTextField(null, null, 0, false);
    256256    private final JProgressBar progressBar = new JProgressBar();
    257257    private final transient ComponentAdapter mvComponentAdapter;
  • trunk/src/org/openstreetmap/josm/gui/dialogs/changeset/ChangesetDetailPanel.java

    r14555 r14977  
    5757
    5858    // CHECKSTYLE.OFF: SingleSpaceSeparator
    59     private final JosmTextField tfID        = new JosmTextField(10);
     59    private final JosmTextField tfID        = new JosmTextField(null, null, 10, false);
    6060    private final JosmTextArea  taComment   = new JosmTextArea(5, 40);
    61     private final JosmTextField tfOpen      = new JosmTextField(10);
    62     private final JosmTextField tfUser      = new JosmTextField("");
    63     private final JosmTextField tfCreatedOn = new JosmTextField(20);
    64     private final JosmTextField tfClosedOn  = new JosmTextField(20);
     61    private final JosmTextField tfOpen      = new JosmTextField(null, null, 10, false);
     62    private final JosmTextField tfUser      = new JosmTextField(null, "", 0);
     63    private final JosmTextField tfCreatedOn = new JosmTextField(null, null, 20, false);
     64    private final JosmTextField tfClosedOn  = new JosmTextField(null, null, 20, false);
    6565
    6666    private final OpenChangesetPopupMenuAction   actOpenChangesetPopupMenu   = new OpenChangesetPopupMenuAction();
  • trunk/src/org/openstreetmap/josm/gui/io/BasicUploadSettingsPanel.java

    r12846 r14977  
    1717import java.util.LinkedList;
    1818import java.util.List;
     19import java.util.Objects;
    1920import java.util.concurrent.TimeUnit;
    2021
     
    3334import org.openstreetmap.josm.gui.widgets.JMultilineLabel;
    3435import org.openstreetmap.josm.spi.preferences.Config;
    35 import org.openstreetmap.josm.tools.CheckParameterUtil;
    3636import org.openstreetmap.josm.tools.GBC;
    3737import org.openstreetmap.josm.tools.Utils;
     
    7878        hcbUploadComment.setToolTipText(tr("Enter an upload comment"));
    7979        hcbUploadComment.setMaxTextLength(Changeset.MAX_CHANGESET_TAG_LENGTH);
    80         List<String> cmtHistory = new LinkedList<>(Config.getPref().getList(HISTORY_KEY, new LinkedList<String>()));
    81         Collections.reverse(cmtHistory); // we have to reverse the history, because ComboBoxHistory will reverse it again in addElement()
    82         hcbUploadComment.setPossibleItems(cmtHistory);
     80        populateHistoryComboBox(hcbUploadComment, HISTORY_KEY, new LinkedList<String>());
    8381        CommentModelListener commentModelListener = new CommentModelListener(hcbUploadComment, changesetCommentModel);
    8482        hcbUploadComment.getEditor().addActionListener(commentModelListener);
     
    9290                final String source = MainApplication.getMap().mapView.getLayerInformationForSourceTag();
    9391                hcbUploadSource.setText(Utils.shortenString(source, Changeset.MAX_CHANGESET_TAG_LENGTH));
    94                 // Fix #9965
    95                 changesetSourceModel.setComment(hcbUploadSource.getText());
     92                changesetSourceModel.setComment(hcbUploadSource.getText()); // Fix #9965
    9693            }
    9794        });
     
    10097        hcbUploadSource.setToolTipText(tr("Enter a source"));
    10198        hcbUploadSource.setMaxTextLength(Changeset.MAX_CHANGESET_TAG_LENGTH);
    102         List<String> sourceHistory = new LinkedList<>(Config.getPref().getList(SOURCE_HISTORY_KEY, getDefaultSources()));
    103         Collections.reverse(sourceHistory); // we have to reverse the history, because ComboBoxHistory will reverse it again in addElement()
    104         hcbUploadSource.setPossibleItems(sourceHistory);
     99        populateHistoryComboBox(hcbUploadSource, SOURCE_HISTORY_KEY, getDefaultSources());
    105100        CommentModelListener sourceModelListener = new CommentModelListener(hcbUploadSource, changesetSourceModel);
    106101        hcbUploadSource.getEditor().addActionListener(sourceModelListener);
     
    108103        pnl.add(hcbUploadSource, GBC.eol().fill(GBC.HORIZONTAL));
    109104        return pnl;
     105    }
     106
     107    /**
     108     * Refreshes contents of upload history combo boxes from preferences.
     109     */
     110    protected void refreshHistoryComboBoxes() {
     111        populateHistoryComboBox(hcbUploadComment, HISTORY_KEY, new LinkedList<String>());
     112        populateHistoryComboBox(hcbUploadSource, SOURCE_HISTORY_KEY, getDefaultSources());
     113    }
     114
     115    private static void populateHistoryComboBox(HistoryComboBox hcb, String historyKey, List<String> defaultValues) {
     116        List<String> cmtHistory = new LinkedList<>(Config.getPref().getList(historyKey, defaultValues));
     117        Collections.reverse(cmtHistory); // we have to reverse the history, because ComboBoxHistory will reverse it again in addElement()
     118        hcb.setPossibleItems(cmtHistory);
     119        hcb.discardAllUndoableEdits();
     120    }
     121
     122    /**
     123     * Discards undoable edits of upload history combo boxes.
     124     */
     125    protected void discardAllUndoableEdits() {
     126        hcbUploadComment.discardAllUndoableEdits();
     127        hcbUploadSource.discardAllUndoableEdits();
    110128    }
    111129
     
    133151     * @param changesetSourceModel the model for the changeset source. Must not be null.
    134152     * @param changesetReviewModel the model for the changeset review. Must not be null.
    135      * @throws IllegalArgumentException if {@code changesetCommentModel} is null
     153     * @throws NullPointerException if a model is null
    136154     * @since 12719 (signature)
    137155     */
    138156    public BasicUploadSettingsPanel(ChangesetCommentModel changesetCommentModel, ChangesetCommentModel changesetSourceModel,
    139157            ChangesetReviewModel changesetReviewModel) {
    140         CheckParameterUtil.ensureParameterNotNull(changesetCommentModel, "changesetCommentModel");
    141         CheckParameterUtil.ensureParameterNotNull(changesetSourceModel, "changesetSourceModel");
    142         CheckParameterUtil.ensureParameterNotNull(changesetReviewModel, "changesetReviewModel");
    143         this.changesetCommentModel = changesetCommentModel;
    144         this.changesetSourceModel = changesetSourceModel;
    145         this.changesetReviewModel = changesetReviewModel;
     158        this.changesetCommentModel = Objects.requireNonNull(changesetCommentModel, "changesetCommentModel");
     159        this.changesetSourceModel = Objects.requireNonNull(changesetSourceModel, "changesetSourceModel");
     160        this.changesetReviewModel = Objects.requireNonNull(changesetReviewModel, "changesetReviewModel");
    146161        changesetCommentModel.addChangeListener(new ChangesetCommentChangeListener(hcbUploadComment));
    147162        changesetSourceModel.addChangeListener(new ChangesetCommentChangeListener(hcbUploadSource));
     
    167182        hcbUploadComment.addCurrentItemToHistory();
    168183        Config.getPref().putList(HISTORY_KEY, hcbUploadComment.getHistory());
    169         Config.getPref().putInt(HISTORY_LAST_USED_KEY, (int) (TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis())));
     184        Config.getPref().putLong(HISTORY_LAST_USED_KEY, TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis()));
    170185        // store the history of sources
    171186        hcbUploadSource.addCurrentItemToHistory();
     
    197212    }
    198213
     214    /**
     215     * Returns the panel that displays a summary of data the user is about to upload.
     216     * @return the upload parameter summary panel
     217     */
    199218    public UploadParameterSummaryPanel getUploadParameterSummaryPanel() {
    200219        return pnlUploadParameterSummary;
     220    }
     221
     222    /**
     223     * Forces update of comment/source model if matching text field is focused.
     224     * @since 14977
     225     */
     226    public void forceUpdateActiveField() {
     227        updateModelIfFocused(hcbUploadComment, changesetCommentModel);
     228        updateModelIfFocused(hcbUploadSource, changesetSourceModel);
     229    }
     230
     231    private static void updateModelIfFocused(HistoryComboBox hcb, ChangesetCommentModel changesetModel) {
     232        if (hcb.getEditorComponent().hasFocus()) {
     233            changesetModel.setComment(hcb.getText());
     234        }
    201235    }
    202236
  • trunk/src/org/openstreetmap/josm/gui/io/ChangesetManagementPanel.java

    r13130 r14977  
    3333
    3434/**
    35  * ChangesetManagementPanel allows to configure changeset to be used in the next
    36  * upload.
     35 * ChangesetManagementPanel allows to configure changeset to be used in the next upload.
    3736 *
    3837 * It is displayed as one of the configuration panels in the {@link UploadDialog}.
    3938 *
    40  * ChangesetManagementPanel is a source for {@link java.beans.PropertyChangeEvent}s. Clients can listen
    41  * to
     39 * ChangesetManagementPanel is a source for {@link java.beans.PropertyChangeEvent}s. Clients can listen to
    4240 * <ul>
    4341 *   <li>{@link #SELECTED_CHANGESET_PROP}  - the new value in the property change event is
    4442 *   the changeset selected by the user. The value is null if the user didn't select a
    45  *   a changeset or if he chosed to use a new changeset.</li>
     43 *   a changeset or if he chose to use a new changeset.</li>
    4644 *   <li> {@link #CLOSE_CHANGESET_AFTER_UPLOAD} - the new value is a boolean value indicating
    4745 *   whether the changeset should be closed after the next upload</li>
  • trunk/src/org/openstreetmap/josm/gui/io/IUploadDialog.java

    r12687 r14977  
    6666     */
    6767    void handleIllegalChunkSize();
     68
     69    /**
     70     * Forces update of comment/source model if matching text field is active.
     71     * @since 14977
     72     */
     73    void forceUpdateActiveField();
    6874}
  • trunk/src/org/openstreetmap/josm/gui/io/TagSettingsPanel.java

    r13198 r14977  
    44import java.awt.BorderLayout;
    55import java.util.Map;
     6import java.util.Objects;
    67import java.util.Optional;
    78
     
    1718import org.openstreetmap.josm.gui.tagging.TagModel;
    1819import org.openstreetmap.josm.spi.preferences.Config;
    19 import org.openstreetmap.josm.tools.CheckParameterUtil;
    2020
    2121/**
     
    3838     * @param changesetSourceModel the changeset source model. Must not be null.
    3939     * @param changesetReviewModel the model for the changeset review. Must not be null.
    40      * @throws IllegalArgumentException if {@code changesetCommentModel} is null
     40     * @throws NullPointerException if a model is null
    4141     * @since 12719 (signature)
    4242     */
    4343    public TagSettingsPanel(ChangesetCommentModel changesetCommentModel, ChangesetCommentModel changesetSourceModel,
    4444            ChangesetReviewModel changesetReviewModel) {
    45         CheckParameterUtil.ensureParameterNotNull(changesetCommentModel, "changesetCommentModel");
    46         CheckParameterUtil.ensureParameterNotNull(changesetSourceModel, "changesetSourceModel");
    47         CheckParameterUtil.ensureParameterNotNull(changesetReviewModel, "changesetReviewModel");
    48         this.changesetCommentModel = changesetCommentModel;
    49         this.changesetSourceModel = changesetSourceModel;
    50         this.changesetReviewModel = changesetReviewModel;
     45        this.changesetCommentModel = Objects.requireNonNull(changesetCommentModel, "changesetCommentModel");
     46        this.changesetSourceModel = Objects.requireNonNull(changesetSourceModel, "changesetSourceModel");
     47        this.changesetReviewModel = Objects.requireNonNull(changesetReviewModel, "changesetReviewModel");
    5148        changesetCommentModel.addChangeListener(new ChangesetCommentChangeListener("comment", "hashtags"));
    5249        changesetSourceModel.addChangeListener(new ChangesetCommentChangeListener("source"));
  • trunk/src/org/openstreetmap/josm/gui/io/UploadDialog.java

    r14355 r14977  
    283283     */
    284284    public void setChangesetTags(DataSet dataSet) {
     285        setChangesetTags(dataSet, false);
     286    }
     287
     288    /**
     289     * Sets the tags for this upload based on (later items overwrite earlier ones):
     290     * <ul>
     291     * <li>previous "source" and "comment" input</li>
     292     * <li>the tags set in the dataset (see {@link DataSet#getChangeSetTags()})</li>
     293     * <li>the tags from the selected open changeset</li>
     294     * <li>the JOSM user agent (see {@link Version#getAgentString(boolean)})</li>
     295     * </ul>
     296     *
     297     * @param dataSet to obtain the tags set in the dataset
     298     * @param keepSourceComment if {@code true}, keep upload {@code source} and {@code comment} current values from models
     299     */
     300    private void setChangesetTags(DataSet dataSet, boolean keepSourceComment) {
    285301        final Map<String, String> tags = new HashMap<>();
    286302
    287303        // obtain from previous input
    288         tags.put("source", getLastChangesetSourceFromHistory());
    289         tags.put("comment", getLastChangesetCommentFromHistory());
     304        if (!keepSourceComment) {
     305            tags.put("source", getLastChangesetSourceFromHistory());
     306            tags.put("comment", getLastChangesetCommentFromHistory());
     307        }
    290308
    291309        // obtain from dataset
     
    318336        }
    319337
     338        // ignore source/comment to keep current values from models ?
     339        if (keepSourceComment) {
     340            tags.put("source", changesetSourceModel.getComment());
     341            tags.put("comment", changesetCommentModel.getComment());
     342        }
     343
    320344        pnlTagSettings.initFromTags(tags);
    321345        pnlTagSettings.tableChanged(null);
     346        pnlBasicUploadSettings.discardAllUndoableEdits();
    322347    }
    323348
     
    519544        @Override
    520545        public void actionPerformed(ActionEvent e) {
     546            // force update of model in case dialog is closed before focus lost event, see #17452
     547            dialog.forceUpdateActiveField();
     548
    521549            if (isUploadCommentTooShort(dialog.getUploadComment()) && warnUploadComment()) {
    522550                // abort for missing comment
     
    620648        if (evt.getPropertyName().equals(ChangesetManagementPanel.SELECTED_CHANGESET_PROP)) {
    621649            Changeset cs = (Changeset) evt.getNewValue();
    622             setChangesetTags(dataSet);
     650            setChangesetTags(dataSet, cs == null); // keep comment/source of first tab for new changesets
    623651            if (cs == null) {
    624652                tpConfigPanels.setTitleAt(1, tr("Tags of new changeset"));
     
    634662    @Override
    635663    public void preferenceChanged(PreferenceChangeEvent e) {
    636         if (e.getKey() == null || !"osm-server.url".equals(e.getKey()))
    637             return;
    638         final Setting<?> newValue = e.getNewValue();
     664        if (e.getKey() != null
     665                && e.getSource() != getClass()
     666                && e.getSource() != BasicUploadSettingsPanel.class) {
     667            switch (e.getKey()) {
     668                case "osm-server.url":
     669                    osmServerUrlChanged(e.getNewValue());
     670                    break;
     671                case BasicUploadSettingsPanel.HISTORY_KEY:
     672                case BasicUploadSettingsPanel.SOURCE_HISTORY_KEY:
     673                    pnlBasicUploadSettings.refreshHistoryComboBoxes();
     674                    break;
     675                default:
     676                    return;
     677            }
     678        }
     679    }
     680
     681    private void osmServerUrlChanged(Setting<?> newValue) {
    639682        final String url;
    640683        if (newValue == null || newValue.getValue() == null) {
     
    648691    private static String getLastChangesetTagFromHistory(String historyKey, List<String> def) {
    649692        Collection<String> history = Config.getPref().getList(historyKey, def);
    650         int age = (int) (System.currentTimeMillis() / 1000 - Config.getPref().getInt(BasicUploadSettingsPanel.HISTORY_LAST_USED_KEY, 0));
    651         if (history != null && age < Config.getPref().getLong(BasicUploadSettingsPanel.HISTORY_MAX_AGE_KEY, TimeUnit.HOURS.toMillis(4))
     693        long age = System.currentTimeMillis() / 1000 - Config.getPref().getLong(BasicUploadSettingsPanel.HISTORY_LAST_USED_KEY, 0);
     694        if (age < Config.getPref().getLong(BasicUploadSettingsPanel.HISTORY_MAX_AGE_KEY, TimeUnit.HOURS.toSeconds(4))
    652695                && !history.isEmpty()) {
    653696            return history.iterator().next();
    654         } else {
    655             return null;
    656         }
     697        }
     698        return null;
    657699    }
    658700
     
    661703     * @return the last changeset comment from history
    662704     */
    663     public String getLastChangesetCommentFromHistory() {
     705    public static String getLastChangesetCommentFromHistory() {
    664706        return getLastChangesetTagFromHistory(BasicUploadSettingsPanel.HISTORY_KEY, new ArrayList<String>());
    665707    }
     
    669711     * @return the last changeset source from history
    670712     */
    671     public String getLastChangesetSourceFromHistory() {
     713    public static String getLastChangesetSourceFromHistory() {
    672714        return getLastChangesetTagFromHistory(BasicUploadSettingsPanel.SOURCE_HISTORY_KEY, BasicUploadSettingsPanel.getDefaultSources());
    673715    }
     
    695737    }
    696738
     739    @Override
     740    public void forceUpdateActiveField() {
     741        if (tpConfigPanels.getSelectedComponent() == pnlBasicUploadSettings) {
     742            pnlBasicUploadSettings.forceUpdateActiveField();
     743        }
     744    }
     745
    697746    /**
    698747     * Clean dialog state and release resources.
  • trunk/src/org/openstreetmap/josm/gui/oauth/AccessTokenInfoPanel.java

    r12686 r14977  
    2222public class AccessTokenInfoPanel extends JPanel {
    2323
    24     private final JosmTextField tfAccessTokenKey = new JosmTextField();
    25     private final JosmTextField tfAccessTokenSecret = new JosmTextField();
     24    private final JosmTextField tfAccessTokenKey = new JosmTextField(null, null, 0, false);
     25    private final JosmTextField tfAccessTokenSecret = new JosmTextField(null, null, 0, false);
    2626    private final JCheckBox cbSaveAccessTokenInPreferences = new JCheckBox(tr("Save Access Token in preferences"));
    2727
  • trunk/src/org/openstreetmap/josm/gui/oauth/SemiAutomaticAuthorizationUI.java

    r12686 r14977  
    211211    private class RetrieveAccessTokenPanel extends JPanel {
    212212
    213         private final JosmTextField tfAuthoriseUrl = new JosmTextField();
     213        private final JosmTextField tfAuthoriseUrl = new JosmTextField(null, null, 0, false);
    214214
    215215        /**
  • trunk/src/org/openstreetmap/josm/gui/preferences/server/OAuthAuthenticationPreferencesPanel.java

    r12931 r14977  
    212212     */
    213213    private class AlreadyAuthorisedPanel extends JPanel {
    214         private final JosmTextField tfAccessTokenKey = new JosmTextField();
    215         private final JosmTextField tfAccessTokenSecret = new JosmTextField();
     214        private final JosmTextField tfAccessTokenKey = new JosmTextField(null, null, 0, false);
     215        private final JosmTextField tfAccessTokenSecret = new JosmTextField(null, null, 0, false);
    216216
    217217        /**
  • trunk/src/org/openstreetmap/josm/gui/widgets/JosmComboBox.java

    r14302 r14977  
    3434 */
    3535public class JosmComboBox<E> extends JComboBox<E> {
     36
     37    private final ContextMenuHandler handler = new ContextMenuHandler();
    3638
    3739    /**
     
    165167
    166168    protected final void init(E prototype) {
     169        init(prototype, true);
     170    }
     171
     172    protected final void init(E prototype, boolean registerPropertyChangeListener) {
    167173        if (prototype != null) {
    168174            setPrototypeDisplayValue(prototype);
     
    186192        }
    187193        // Handle text contextual menus for editable comboboxes
    188         ContextMenuHandler handler = new ContextMenuHandler();
    189         addPropertyChangeListener("editable", handler);
    190         addPropertyChangeListener("editor", handler);
     194        if (registerPropertyChangeListener) {
     195            addPropertyChangeListener("editable", handler);
     196            addPropertyChangeListener("editor", handler);
     197        }
    191198    }
    192199
     
    232239        }
    233240
     241        private void discardAllUndoableEdits() {
     242            if (launcher != null) {
     243                launcher.discardAllUndoableEdits();
     244            }
     245        }
     246
    234247        @Override
    235248        public void mousePressed(MouseEvent e) {
     
    250263
    251264    /**
    252      * Reinitializes this {@link JosmComboBox} to the specified values. This may needed if a custom renderer is used.
     265     * Reinitializes this {@link JosmComboBox} to the specified values. This may be needed if a custom renderer is used.
    253266     * @param values The values displayed in the combo box.
    254267     * @since 5558
    255268     */
    256269    public final void reinitialize(Collection<E> values) {
    257         init(findPrototypeDisplayValue(values));
     270        init(findPrototypeDisplayValue(values), false);
     271        discardAllUndoableEdits();
     272    }
     273
     274    /**
     275     * Empties the internal undo manager, if any.
     276     * @since 14977
     277     */
     278    public final void discardAllUndoableEdits() {
     279        handler.discardAllUndoableEdits();
    258280    }
    259281}
  • trunk/src/org/openstreetmap/josm/gui/widgets/JosmImageView.java

    r13649 r14977  
    1717import org.openstreetmap.josm.tools.ImageProvider;
    1818import org.openstreetmap.josm.tools.Logging;
    19 import org.openstreetmap.josm.tools.Utils;
     19import org.openstreetmap.josm.tools.ReflectionUtils;
    2020
    2121/**
     
    4848        widthField = getDeclaredField("width");
    4949        heightField = getDeclaredField("height");
    50         Utils.setObjectsAccessible(imageField, stateField, widthField, heightField);
     50        ReflectionUtils.setObjectsAccessible(imageField, stateField, widthField, heightField);
    5151    }
    5252
     
    108108            // And update the size params
    109109            Method updateImageSize = ImageView.class.getDeclaredMethod("updateImageSize");
    110             Utils.setObjectsAccessible(updateImageSize);
     110            ReflectionUtils.setObjectsAccessible(updateImageSize);
    111111            updateImageSize.invoke(this);
    112112        } finally {
     
    136136            } else {
    137137                Method loadImage = ImageView.class.getDeclaredMethod("loadImage");
    138                 Utils.setObjectsAccessible(loadImage);
     138                ReflectionUtils.setObjectsAccessible(loadImage);
    139139                loadImage.invoke(this);
    140140            }
  • trunk/src/org/openstreetmap/josm/gui/widgets/JosmTextField.java

    r14463 r14977  
    146146    public final void setHint(String hint) {
    147147        this.hint = hint;
     148    }
     149
     150    /**
     151     * Empties the internal undo manager.
     152     * @since 14977
     153     */
     154    public final void discardAllUndoableEdits() {
     155        launcher.discardAllUndoableEdits();
    148156    }
    149157
  • trunk/src/org/openstreetmap/josm/gui/widgets/PopupMenuLauncher.java

    r14676 r14977  
    155155        return menu;
    156156    }
     157
     158    /**
     159     * Empties the internal undo manager, if any.
     160     * @since 14977
     161     */
     162    public void discardAllUndoableEdits() {
     163        if (menu instanceof TextContextualPopupMenu) {
     164            ((TextContextualPopupMenu) menu).discardAllUndoableEdits();
     165        }
     166    }
    157167}
  • trunk/src/org/openstreetmap/josm/gui/widgets/TextContextualPopupMenu.java

    r14138 r14977  
    6161    protected final transient UndoableEditListener undoEditListener = e -> {
    6262        undo.addEdit(e.getEdit());
    63         undoAction.updateUndoState();
    64         redoAction.updateRedoState();
     63        updateUndoRedoState();
    6564    };
    6665
     
    7776    protected TextContextualPopupMenu() {
    7877        // Restricts visibility
     78    }
     79
     80    private void updateUndoRedoState() {
     81        undoAction.updateUndoState();
     82        redoAction.updateRedoState();
    7983    }
    8084
     
    9094        if (component != null && !isAttached()) {
    9195            this.component = component;
    92             this.undoRedo = undoRedo;
    9396            if (undoRedo && component.isEditable()) {
    94                 component.getDocument().addUndoableEditListener(undoEditListener);
    95                 if (!GraphicsEnvironment.isHeadless()) {
    96                     component.getInputMap().put(
    97                             KeyStroke.getKeyStroke(KeyEvent.VK_Z, PlatformManager.getPlatform().getMenuShortcutKeyMaskEx()), undoAction);
    98                     component.getInputMap().put(
    99                             KeyStroke.getKeyStroke(KeyEvent.VK_Y, PlatformManager.getPlatform().getMenuShortcutKeyMaskEx()), redoAction);
    100                 }
     97                enableUndoRedo();
    10198            }
    10299            addMenuEntries();
     
    104101        }
    105102        return this;
     103    }
     104
     105    private void enableUndoRedo() {
     106        if (!undoRedo) {
     107            component.getDocument().addUndoableEditListener(undoEditListener);
     108            if (!GraphicsEnvironment.isHeadless()) {
     109                component.getInputMap().put(
     110                        KeyStroke.getKeyStroke(KeyEvent.VK_Z, PlatformManager.getPlatform().getMenuShortcutKeyMaskEx()), undoAction);
     111                component.getInputMap().put(
     112                        KeyStroke.getKeyStroke(KeyEvent.VK_Y, PlatformManager.getPlatform().getMenuShortcutKeyMaskEx()), redoAction);
     113            }
     114            undoRedo = true;
     115        }
     116    }
     117
     118    private void disableUndoRedo() {
     119        if (undoRedo) {
     120            if (!GraphicsEnvironment.isHeadless()) {
     121                component.getInputMap().remove(
     122                        KeyStroke.getKeyStroke(KeyEvent.VK_Z, PlatformManager.getPlatform().getMenuShortcutKeyMaskEx()));
     123                component.getInputMap().remove(
     124                        KeyStroke.getKeyStroke(KeyEvent.VK_Y, PlatformManager.getPlatform().getMenuShortcutKeyMaskEx()));
     125            }
     126            component.getDocument().removeUndoableEditListener(undoEditListener);
     127            undoRedo = false;
     128        }
    106129    }
    107130
     
    134157            removeAll();
    135158            if (undoRedo) {
    136                 component.getDocument().removeUndoableEditListener(undoEditListener);
     159                disableUndoRedo();
    137160            }
    138161            component = null;
     
    166189            component.removeMouseListener(launcher);
    167190        }
     191    }
     192
     193    /**
     194     * Empties the internal undo manager.
     195     * @since 14977
     196     */
     197    public void discardAllUndoableEdits() {
     198        undo.discardAllEdits();
     199        updateUndoRedoState();
    168200    }
    169201
  • trunk/src/org/openstreetmap/josm/spi/preferences/DefaultPreferenceChangeEvent.java

    r12882 r14977  
    11// License: GPL. For details, see LICENSE file.
    22package org.openstreetmap.josm.spi.preferences;
     3
     4import java.util.EventObject;
    35
    46/**
     
    68 * @since 12881
    79 */
    8 public class DefaultPreferenceChangeEvent implements PreferenceChangeEvent {
    9    
     10public class DefaultPreferenceChangeEvent extends EventObject implements PreferenceChangeEvent {
     11
    1012    private final String key;
    1113    private final Setting<?> oldValue;
    1214    private final Setting<?> newValue;
    1315
    14     public DefaultPreferenceChangeEvent(String key, Setting<?> oldValue, Setting<?> newValue) {
     16    /**
     17     * Constructs a new {@code DefaultPreferenceChangeEvent}.
     18     * @param source the class source of this event
     19     * @param key preference key
     20     * @param oldValue preference old value
     21     * @param newValue preference new value
     22     * @since 14977
     23     */
     24    public DefaultPreferenceChangeEvent(Class<?> source, String key, Setting<?> oldValue, Setting<?> newValue) {
     25        super(source);
    1526        this.key = key;
    1627        this.oldValue = oldValue;
    1728        this.newValue = newValue;
     29    }
     30
     31    @Override
     32    public Class<?> getSource() {
     33        return (Class<?>) super.getSource();
    1834    }
    1935
     
    3248        return newValue;
    3349    }
    34    
     50
    3551}
  • trunk/src/org/openstreetmap/josm/spi/preferences/PreferenceChangeEvent.java

    r12882 r14977  
    77 */
    88public interface PreferenceChangeEvent {
     9
     10    /**
     11     * Returns the class source of this event.
     12     * @return The class source of this event
     13     * @since 14977
     14     */
     15    Class<?> getSource();
    916
    1017    /**
     
    2532     */
    2633    Setting<?> getNewValue();
    27    
    2834}
  • trunk/src/org/openstreetmap/josm/tools/Utils.java

    r14535 r14977  
    3030import java.nio.file.attribute.BasicFileAttributes;
    3131import java.nio.file.attribute.FileTime;
    32 import java.security.AccessController;
    3332import java.security.MessageDigest;
    3433import java.security.NoSuchAlgorithmException;
    35 import java.security.PrivilegedAction;
    3634import java.text.Bidi;
    3735import java.text.DateFormat;
     
    15591557     * @param objects objects
    15601558     * @see AccessibleObject#setAccessible
     1559     * @deprecated Use {@link ReflectionUtils#setObjectsAccessible(AccessibleObject...)}
    15611560     * @since 10223
    15621561     */
     1562    @Deprecated
    15631563    public static void setObjectsAccessible(final AccessibleObject... objects) {
    1564         if (objects != null && objects.length > 0) {
    1565             AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
    1566                 for (AccessibleObject o : objects) {
    1567                     if (o != null) {
    1568                         o.setAccessible(true);
    1569                     }
    1570                 }
    1571                 return null;
    1572             });
    1573         }
     1564        ReflectionUtils.setObjectsAccessible(objects);
    15741565    }
    15751566
  • trunk/src/org/openstreetmap/josm/tools/WinRegistry.java

    r13672 r14977  
    6363        regQueryInfoKey = getDeclaredMethod("WindowsRegQueryInfoKey1", int.class);
    6464        regEnumKeyEx = getDeclaredMethod("WindowsRegEnumKeyEx", int.class, int.class, int.class);
    65         Utils.setObjectsAccessible(regOpenKey, regCloseKey, regQueryValueEx, regEnumValue, regQueryInfoKey, regEnumKeyEx);
     65        ReflectionUtils.setObjectsAccessible(regOpenKey, regCloseKey, regQueryValueEx, regEnumValue, regQueryInfoKey, regEnumKeyEx);
    6666    }
    6767
  • trunk/test/unit/org/openstreetmap/josm/TestUtils.java

    r14782 r14977  
    5454import org.openstreetmap.josm.testutils.mockers.WindowMocker;
    5555import org.openstreetmap.josm.tools.JosmRuntimeException;
     56import org.openstreetmap.josm.tools.ReflectionUtils;
    5657import org.openstreetmap.josm.tools.Utils;
    5758import org.openstreetmap.josm.tools.WikiReader;
     
    413414            Method values = enumClass.getMethod("values");
    414415            Method valueOf = enumClass.getMethod("valueOf", String.class);
    415             Utils.setObjectsAccessible(values, valueOf);
     416            ReflectionUtils.setObjectsAccessible(values, valueOf);
    416417            for (Object o : (Object[]) values.invoke(null)) {
    417418                assertEquals(o, valueOf.invoke(null, ((Enum<?>) o).name()));
  • trunk/test/unit/org/openstreetmap/josm/actions/CreateCircleActionTest.java

    r14542 r14977  
    2121import org.openstreetmap.josm.tools.GeoPropertyIndex;
    2222import org.openstreetmap.josm.tools.Geometry;
     23import org.openstreetmap.josm.tools.ReflectionUtils;
    2324import org.openstreetmap.josm.tools.RightAndLefthandTraffic;
    24 import org.openstreetmap.josm.tools.Utils;
    2525
    2626import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
     
    118118        // Mock left/right hand traffic database
    119119        Field rlCache = RightAndLefthandTraffic.class.getDeclaredField("rlCache");
    120         Utils.setObjectsAccessible(rlCache);
     120        ReflectionUtils.setObjectsAccessible(rlCache);
    121121        Object origRlCache = rlCache.get(null);
    122122        rlCache.set(null, new GeoPropertyIndex<>(new ConstantTrafficHand(true), 24));
  • trunk/test/unit/org/openstreetmap/josm/actions/mapmode/SelectActionTest.java

    r14138 r14977  
    2727import org.openstreetmap.josm.spi.preferences.Config;
    2828import org.openstreetmap.josm.testutils.JOSMTestRules;
    29 import org.openstreetmap.josm.tools.Utils;
     29import org.openstreetmap.josm.tools.ReflectionUtils;
    3030
    3131import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
     
    4242            super(mapFrame);
    4343            Field mv = SelectAction.class.getDeclaredField("mv");
    44             Utils.setObjectsAccessible(mv);
     44            ReflectionUtils.setObjectsAccessible(mv);
    4545            mv.set(this, new MapViewMock(new MainLayerManager()));
    4646        }
  • trunk/test/unit/org/openstreetmap/josm/gui/TableCellRendererTest.java

    r14138 r14977  
    2020import org.openstreetmap.josm.testutils.JOSMTestRules;
    2121import org.openstreetmap.josm.tools.Logging;
    22 import org.openstreetmap.josm.tools.Utils;
     22import org.openstreetmap.josm.tools.ReflectionUtils;
    2323
    2424import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
     
    9999            c = klass.getDeclaredConstructor();
    100100        }
    101         Utils.setObjectsAccessible(c);
     101        ReflectionUtils.setObjectsAccessible(c);
    102102        if (needOuterClass) {
    103103            return c.newInstance(createInstance(klass.getDeclaringClass()));
  • trunk/test/unit/org/openstreetmap/josm/gui/io/UploadDialogTest.java

    r14355 r14977  
    44import static org.junit.Assert.assertEquals;
    55import static org.junit.Assert.assertFalse;
     6import static org.junit.Assert.assertNull;
    67import static org.junit.Assert.assertTrue;
    78
    89import java.awt.GraphicsEnvironment;
     10import java.util.Arrays;
    911import java.util.List;
    1012import java.util.Map;
    1113import java.util.concurrent.ConcurrentHashMap;
     14import java.util.function.Supplier;
     15
    1216import javax.swing.JButton;
    1317import javax.swing.JOptionPane;
     
    1519import org.junit.Rule;
    1620import org.junit.Test;
     21import org.openstreetmap.josm.TestUtils;
    1722import org.openstreetmap.josm.gui.ExtendedDialog;
    18 import org.openstreetmap.josm.TestUtils;
    1923import org.openstreetmap.josm.io.UploadStrategySpecification;
     24import org.openstreetmap.josm.spi.preferences.Config;
    2025import org.openstreetmap.josm.testutils.JOSMTestRules;
    2126import org.openstreetmap.josm.testutils.mockers.ExtendedDialogMocker;
    2227import org.openstreetmap.josm.testutils.mockers.WindowMocker;
    2328
     29import com.google.common.collect.ImmutableMap;
     30
     31import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
    2432import mockit.Invocation;
    2533import mockit.Mock;
    26 
    27 import com.google.common.collect.ImmutableMap;
    28 
    29 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
    3034
    3135/**
     
    96100        public Map<String, String> getTags(boolean keepEmpty) {
    97101            return new ConcurrentHashMap<>();
     102        }
     103
     104        @Override
     105        public void forceUpdateActiveField() {
     106            // Do nothing
    98107        }
    99108    }
     
    214223        assertTrue(UploadDialog.UploadAction.isUploadCommentTooShort("\u0860"));
    215224    }
     225
     226    private static void doTestGetLastChangesetTagFromHistory(String historyKey, Supplier<String> methodToTest, String def) {
     227        Config.getPref().putList(historyKey, null);
     228        Config.getPref().putInt(BasicUploadSettingsPanel.HISTORY_LAST_USED_KEY, 0);
     229        Config.getPref().putInt(BasicUploadSettingsPanel.HISTORY_MAX_AGE_KEY, 30);
     230        assertNull(methodToTest.get());          // age NOK (history empty)
     231        Config.getPref().putList(historyKey, Arrays.asList("foo"));
     232        assertNull(methodToTest.get());          // age NOK (history not empty)
     233        Config.getPref().putLong(BasicUploadSettingsPanel.HISTORY_LAST_USED_KEY, System.currentTimeMillis() / 1000);
     234        assertEquals("foo", methodToTest.get()); // age OK, history not empty
     235        Config.getPref().putList(historyKey, null);
     236        assertEquals(def, methodToTest.get());   // age OK, history empty
     237    }
     238
     239    /**
     240     * Test of {@link UploadDialog#getLastChangesetCommentFromHistory} method.
     241     */
     242    @Test
     243    public void testGetLastChangesetCommentFromHistory() {
     244        doTestGetLastChangesetTagFromHistory(
     245                BasicUploadSettingsPanel.HISTORY_KEY,
     246                UploadDialog::getLastChangesetCommentFromHistory,
     247                null);
     248    }
     249
     250    /**
     251     * Test of {@link UploadDialog#getLastChangesetSourceFromHistory} method.
     252     */
     253    @Test
     254    public void testGetLastChangesetSourceFromHistory() {
     255        doTestGetLastChangesetTagFromHistory(
     256                BasicUploadSettingsPanel.SOURCE_HISTORY_KEY,
     257                UploadDialog::getLastChangesetSourceFromHistory,
     258                BasicUploadSettingsPanel.getDefaultSources().get(0));
     259    }
    216260}
Note: See TracChangeset for help on using the changeset viewer.