001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.dialogs.changeset.query;
003
004import static org.openstreetmap.josm.tools.I18n.tr;
005
006import java.awt.BorderLayout;
007import java.awt.GridBagConstraints;
008import java.awt.GridBagLayout;
009import java.awt.event.ItemEvent;
010import java.awt.event.ItemListener;
011
012import javax.swing.BorderFactory;
013import javax.swing.JCheckBox;
014import javax.swing.JPanel;
015import javax.swing.JScrollPane;
016
017import org.openstreetmap.josm.gui.util.GuiHelper;
018import org.openstreetmap.josm.gui.widgets.JMultilineLabel;
019import org.openstreetmap.josm.gui.widgets.VerticallyScrollablePanel;
020import org.openstreetmap.josm.io.ChangesetQuery;
021import org.openstreetmap.josm.spi.preferences.Config;
022
023/**
024 * This panel allows to specify a changeset query
025 * @since 2689
026 */
027public class AdvancedChangesetQueryPanel extends JPanel {
028
029    private final JCheckBox cbUserRestriction = new JCheckBox();
030    private final JCheckBox cbOpenAndCloseRestrictions = new JCheckBox();
031    private final JCheckBox cbTimeRestrictions = new JCheckBox();
032    private final JCheckBox cbBoundingBoxRestriction = new JCheckBox();
033    private final UserRestrictionPanel pnlUserRestriction = new UserRestrictionPanel();
034    private final OpenAndCloseStateRestrictionPanel pnlOpenAndCloseRestriction = new OpenAndCloseStateRestrictionPanel();
035    private final TimeRestrictionPanel pnlTimeRestriction = new TimeRestrictionPanel();
036    private final BBoxRestrictionPanel pnlBoundingBoxRestriction = new BBoxRestrictionPanel();
037
038    /**
039     * Constructs a new {@code AdvancedChangesetQueryPanel}.
040     */
041    public AdvancedChangesetQueryPanel() {
042        build();
043    }
044
045    protected JPanel buildQueryPanel() {
046        ItemListener stateChangeHandler = new RestrictionGroupStateChangeHandler();
047        JPanel pnl = new VerticallyScrollablePanel(new GridBagLayout());
048        pnl.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
049        GridBagConstraints gc = new GridBagConstraints();
050
051        // -- select changesets by a specific user
052        //
053        gc.anchor = GridBagConstraints.NORTHWEST;
054        gc.weightx = 0.0;
055        gc.fill = GridBagConstraints.HORIZONTAL;
056        pnl.add(cbUserRestriction, gc);
057        cbUserRestriction.addItemListener(stateChangeHandler);
058
059        gc.gridx = 1;
060        gc.weightx = 1.0;
061        pnl.add(new JMultilineLabel(tr("Select changesets owned by specific users")), gc);
062
063        gc.gridy = 1;
064        gc.gridx = 1;
065        gc.weightx = 1.0;
066        pnl.add(pnlUserRestriction, gc);
067
068        // -- restricting the query to open and closed changesets
069        //
070        gc.gridy = 2;
071        gc.gridx = 0;
072        gc.anchor = GridBagConstraints.NORTHWEST;
073        gc.weightx = 0.0;
074        gc.fill = GridBagConstraints.HORIZONTAL;
075        pnl.add(cbOpenAndCloseRestrictions, gc);
076        cbOpenAndCloseRestrictions.addItemListener(stateChangeHandler);
077
078        gc.gridx = 1;
079        gc.weightx = 1.0;
080        pnl.add(new JMultilineLabel(tr("Select changesets depending on whether they are open or closed")), gc);
081
082        gc.gridy = 3;
083        gc.gridx = 1;
084        gc.weightx = 1.0;
085        pnl.add(pnlOpenAndCloseRestriction, gc);
086
087        // -- restricting the query to a specific time
088        //
089        gc.gridy = 4;
090        gc.gridx = 0;
091        gc.anchor = GridBagConstraints.NORTHWEST;
092        gc.weightx = 0.0;
093        gc.fill = GridBagConstraints.HORIZONTAL;
094        pnl.add(cbTimeRestrictions, gc);
095        cbTimeRestrictions.addItemListener(stateChangeHandler);
096
097        gc.gridx = 1;
098        gc.weightx = 1.0;
099        pnl.add(new JMultilineLabel(tr("Select changesets based on the date/time they have been created or closed")), gc);
100
101        gc.gridy = 5;
102        gc.gridx = 1;
103        gc.weightx = 1.0;
104        pnl.add(pnlTimeRestriction, gc);
105
106
107        // -- restricting the query to a specific bounding box
108        //
109        gc.gridy = 6;
110        gc.gridx = 0;
111        gc.anchor = GridBagConstraints.NORTHWEST;
112        gc.weightx = 0.0;
113        gc.fill = GridBagConstraints.HORIZONTAL;
114        pnl.add(cbBoundingBoxRestriction, gc);
115        cbBoundingBoxRestriction.addItemListener(stateChangeHandler);
116
117        gc.gridx = 1;
118        gc.weightx = 1.0;
119        pnl.add(new JMultilineLabel(tr("Select only changesets related to a specific bounding box")), gc);
120
121        gc.gridy = 7;
122        gc.gridx = 1;
123        gc.weightx = 1.0;
124        pnl.add(pnlBoundingBoxRestriction, gc);
125
126
127        gc.gridy = 8;
128        gc.gridx = 0;
129        gc.gridwidth = 2;
130        gc.fill = GridBagConstraints.BOTH;
131        gc.weightx = 1.0;
132        gc.weighty = 1.0;
133        pnl.add(new JPanel(), gc);
134
135        return pnl;
136    }
137
138    protected final void build() {
139        setLayout(new BorderLayout());
140        JScrollPane spQueryPanel = GuiHelper.embedInVerticalScrollPane(buildQueryPanel());
141        add(spQueryPanel, BorderLayout.CENTER);
142    }
143
144    /**
145     * Initializes HMI for user input.
146     */
147    public void startUserInput() {
148        restoreFromSettings();
149        pnlBoundingBoxRestriction.setVisible(cbBoundingBoxRestriction.isSelected());
150        pnlOpenAndCloseRestriction.setVisible(cbOpenAndCloseRestrictions.isSelected());
151        pnlTimeRestriction.setVisible(cbTimeRestrictions.isSelected());
152        pnlUserRestriction.setVisible(cbUserRestriction.isSelected());
153        pnlOpenAndCloseRestriction.startUserInput();
154        pnlUserRestriction.startUserInput();
155        pnlTimeRestriction.startUserInput();
156    }
157
158    /**
159     * Display error message if a field is invalid.
160     */
161    public void displayMessageIfInvalid() {
162        if (cbUserRestriction.isSelected()) {
163            if (!pnlUserRestriction.isValidChangesetQuery()) {
164                pnlUserRestriction.displayMessageIfInvalid();
165            }
166        } else if (cbTimeRestrictions.isSelected()) {
167            if (!pnlTimeRestriction.isValidChangesetQuery()) {
168                pnlTimeRestriction.displayMessageIfInvalid();
169            }
170        } else if (cbBoundingBoxRestriction.isSelected()) {
171            if (!pnlBoundingBoxRestriction.isValidChangesetQuery()) {
172                pnlBoundingBoxRestriction.displayMessageIfInvalid();
173            }
174        }
175    }
176
177    /**
178     * Builds the changeset query based on the data entered in the form.
179     *
180     * @return the changeset query. null, if the data entered doesn't represent
181     * a valid changeset query.
182     */
183    public ChangesetQuery buildChangesetQuery() {
184        ChangesetQuery query = new ChangesetQuery();
185        if (cbUserRestriction.isSelected()) {
186            if (!pnlUserRestriction.isValidChangesetQuery())
187                return null;
188            pnlUserRestriction.fillInQuery(query);
189        }
190        if (cbOpenAndCloseRestrictions.isSelected()) {
191            // don't have to check whether it's valid. It always is.
192            pnlOpenAndCloseRestriction.fillInQuery(query);
193        }
194        if (cbBoundingBoxRestriction.isSelected()) {
195            if (!pnlBoundingBoxRestriction.isValidChangesetQuery())
196                return null;
197            pnlBoundingBoxRestriction.fillInQuery(query);
198        }
199        if (cbTimeRestrictions.isSelected()) {
200            if (!pnlTimeRestriction.isValidChangesetQuery())
201                return null;
202            pnlTimeRestriction.fillInQuery(query);
203        }
204        return query;
205    }
206
207    /**
208     * Remember settings in preferences.
209     */
210    public void rememberSettings() {
211        Config.getPref().putBoolean("changeset-query.advanced.user-restrictions", cbUserRestriction.isSelected());
212        Config.getPref().putBoolean("changeset-query.advanced.open-restrictions", cbOpenAndCloseRestrictions.isSelected());
213        Config.getPref().putBoolean("changeset-query.advanced.time-restrictions", cbTimeRestrictions.isSelected());
214        Config.getPref().putBoolean("changeset-query.advanced.bbox-restrictions", cbBoundingBoxRestriction.isSelected());
215
216        pnlUserRestriction.rememberSettings();
217        pnlOpenAndCloseRestriction.rememberSettings();
218        pnlTimeRestriction.rememberSettings();
219    }
220
221    /**
222     * Restore settings from preferences.
223     */
224    public void restoreFromSettings() {
225        cbUserRestriction.setSelected(Config.getPref().getBoolean("changeset-query.advanced.user-restrictions", false));
226        cbOpenAndCloseRestrictions.setSelected(Config.getPref().getBoolean("changeset-query.advanced.open-restrictions", false));
227        cbTimeRestrictions.setSelected(Config.getPref().getBoolean("changeset-query.advanced.time-restrictions", false));
228        cbBoundingBoxRestriction.setSelected(Config.getPref().getBoolean("changeset-query.advanced.bbox-restrictions", false));
229    }
230
231    class RestrictionGroupStateChangeHandler implements ItemListener {
232        protected void userRestrictionStateChanged() {
233            if (pnlUserRestriction == null)
234                return;
235            pnlUserRestriction.setVisible(cbUserRestriction.isSelected());
236        }
237
238        protected void openCloseRestrictionStateChanged() {
239            if (pnlOpenAndCloseRestriction == null)
240                return;
241            pnlOpenAndCloseRestriction.setVisible(cbOpenAndCloseRestrictions.isSelected());
242        }
243
244        protected void timeRestrictionsStateChanged() {
245            if (pnlTimeRestriction == null)
246                return;
247            pnlTimeRestriction.setVisible(cbTimeRestrictions.isSelected());
248        }
249
250        protected void boundingBoxRestrictionChanged() {
251            if (pnlBoundingBoxRestriction == null)
252                return;
253            pnlBoundingBoxRestriction.setVisible(cbBoundingBoxRestriction.isSelected());
254        }
255
256        @Override
257        public void itemStateChanged(ItemEvent e) {
258            if (e.getSource() == cbUserRestriction) {
259                userRestrictionStateChanged();
260            } else if (e.getSource() == cbOpenAndCloseRestrictions) {
261                openCloseRestrictionStateChanged();
262            } else if (e.getSource() == cbTimeRestrictions) {
263                timeRestrictionsStateChanged();
264            } else if (e.getSource() == cbBoundingBoxRestriction) {
265                boundingBoxRestrictionChanged();
266            }
267            validate();
268            repaint();
269        }
270    }
271}