001    // License: GPL. For details, see LICENSE file.
002    package org.openstreetmap.josm.gui.io;
003    
004    import static org.openstreetmap.josm.tools.I18n.tr;
005    
006    import java.awt.BorderLayout;
007    import java.awt.GridBagLayout;
008    import java.awt.event.ActionEvent;
009    import java.awt.event.ActionListener;
010    import java.awt.event.FocusAdapter;
011    import java.awt.event.FocusEvent;
012    import java.awt.event.KeyEvent;
013    import java.awt.event.KeyListener;
014    import java.util.Collections;
015    import java.util.LinkedList;
016    import java.util.List;
017    import java.util.Observable;
018    import java.util.Observer;
019    
020    import javax.swing.Action;
021    import javax.swing.BorderFactory;
022    import javax.swing.JLabel;
023    import javax.swing.JPanel;
024    
025    import org.openstreetmap.josm.Main;
026    import org.openstreetmap.josm.data.osm.Changeset;
027    import org.openstreetmap.josm.gui.widgets.HistoryComboBox;
028    import org.openstreetmap.josm.tools.CheckParameterUtil;
029    import org.openstreetmap.josm.tools.GBC;
030    
031    /**
032     * BasicUploadSettingsPanel allows to enter the basic parameters required for uploading
033     * data.
034     *
035     */
036    public class BasicUploadSettingsPanel extends JPanel {
037        public static final String HISTORY_KEY = "upload.comment.history";
038        public static final String HISTORY_LAST_USED_KEY = "upload.comment.last-used";
039    
040        /** the history combo box for the upload comment */
041        private HistoryComboBox hcbUploadComment;
042        /** the panel with a summary of the upload parameters */
043        private UploadParameterSummaryPanel pnlUploadParameterSummary;
044        /** the changset comment model */
045        private ChangesetCommentModel changesetCommentModel;
046    
047        protected JPanel buildUploadCommentPanel() {
048            JPanel pnl = new JPanel();
049            pnl.setLayout(new GridBagLayout());
050            pnl.add(new JLabel(tr("Provide a brief comment for the changes you are uploading:")), GBC.eol().insets(0, 5, 10, 3));
051            hcbUploadComment = new HistoryComboBox();
052            hcbUploadComment.setToolTipText(tr("Enter an upload comment"));
053            hcbUploadComment.setMaxTextLength(Changeset.MAX_COMMENT_LENGTH);
054            List<String> cmtHistory = new LinkedList<String>(Main.pref.getCollection(HISTORY_KEY, new LinkedList<String>()));
055            // we have to reverse the history, because ComboBoxHistory will reverse it again
056            // in addElement()
057            //
058            Collections.reverse(cmtHistory);
059            hcbUploadComment.setPossibleItems(cmtHistory);
060            hcbUploadComment.getEditor().addActionListener(
061                    new ActionListener() {
062                        public void actionPerformed(ActionEvent e) {
063                            changesetCommentModel.setComment(hcbUploadComment.getText());
064                        }
065                    }
066            );
067            hcbUploadComment.getEditor().getEditorComponent().addFocusListener(
068                    new FocusAdapter() {
069                        @Override
070                        public void focusLost(FocusEvent e) {
071                            changesetCommentModel.setComment(hcbUploadComment.getText());
072                        }
073                    }
074            );
075            pnl.add(hcbUploadComment, GBC.eol().fill(GBC.HORIZONTAL));
076            return pnl;
077        }
078    
079        protected void build() {
080            setLayout(new BorderLayout());
081            setBorder(BorderFactory.createEmptyBorder(3,3,3,3));
082            add(buildUploadCommentPanel(), BorderLayout.NORTH);
083            add(pnlUploadParameterSummary = new UploadParameterSummaryPanel(), BorderLayout.CENTER);
084        }
085    
086        /**
087         * Creates the panel
088         *
089         * @param changesetCommentModel the model for the changeset comment. Must not be null
090         * @throws IllegalArgumentException thrown if {@code changesetCommentModel} is null
091         */
092        public BasicUploadSettingsPanel(ChangesetCommentModel changesetCommentModel) {
093            CheckParameterUtil.ensureParameterNotNull(changesetCommentModel, "changesetCommentModel");
094            this.changesetCommentModel = changesetCommentModel;
095            changesetCommentModel.addObserver(new ChangesetCommentObserver());
096            build();
097        }
098    
099        public void setUploadCommentDownFocusTraversalHandler(final Action handler) {
100            hcbUploadComment.getEditor().addActionListener(handler);
101            hcbUploadComment.getEditor().getEditorComponent().addKeyListener(
102                    new KeyListener() {
103                        public void keyTyped(KeyEvent e) {
104                            if (e.getKeyCode() == KeyEvent.VK_TAB) {
105                                handler.actionPerformed(new ActionEvent(hcbUploadComment,0, "focusDown"));
106                            }
107                        }
108                        public void keyReleased(KeyEvent e) {}
109    
110                        public void keyPressed(KeyEvent e) {}
111                    }
112            );
113        }
114    
115        /**
116         * Remembers the user input in the preference settings
117         */
118        public void rememberUserInput() {
119            // store the history of comments
120            hcbUploadComment.addCurrentItemToHistory();
121            Main.pref.putCollection(HISTORY_KEY, hcbUploadComment.getHistory());
122            Main.pref.putInteger(HISTORY_LAST_USED_KEY, (int) (System.currentTimeMillis() / 1000));
123        }
124    
125        /**
126         * Initializes the panel for user input
127         */
128        public void startUserInput() {
129            List<String> history = hcbUploadComment.getHistory();
130            int age = (int) (System.currentTimeMillis()/1000 - Main.pref.getInteger(HISTORY_LAST_USED_KEY, 0));
131            // only pre-select latest entry if used less than 4 hours ago.
132            if (age < 4 * 3600 * 1000 && history != null && !history.isEmpty()) {
133                hcbUploadComment.setText(history.get(0));
134            }
135            hcbUploadComment.requestFocusInWindow();
136            hcbUploadComment.getEditor().getEditorComponent().requestFocusInWindow();
137        }
138    
139        public void initEditingOfUploadComment() {
140            hcbUploadComment.getEditor().selectAll();
141            hcbUploadComment.requestFocusInWindow();
142        }
143    
144        public UploadParameterSummaryPanel getUploadParameterSummaryPanel() {
145            return pnlUploadParameterSummary;
146        }
147    
148        /**
149         * Observes the changeset comment model and keeps the comment input field
150         * in sync with the current changeset comment
151         */
152        class ChangesetCommentObserver implements Observer {
153            public void update(Observable o, Object arg) {
154                if (!(o instanceof ChangesetCommentModel)) return;
155                String newComment = (String)arg;
156                if (!hcbUploadComment.getText().equals(newComment)) {
157                    hcbUploadComment.setText(newComment);
158                }
159            }
160        }
161    }