001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.dialogs.changeset;
003
004import static org.openstreetmap.josm.tools.I18n.tr;
005
006import java.awt.BorderLayout;
007import java.awt.Component;
008import java.awt.FlowLayout;
009import java.awt.event.ActionEvent;
010import java.beans.PropertyChangeEvent;
011import java.beans.PropertyChangeListener;
012import java.util.Collections;
013
014import javax.swing.AbstractAction;
015import javax.swing.BorderFactory;
016import javax.swing.JPanel;
017import javax.swing.JScrollPane;
018import javax.swing.JTable;
019import javax.swing.JToolBar;
020
021import org.openstreetmap.josm.Main;
022import org.openstreetmap.josm.data.osm.Changeset;
023import org.openstreetmap.josm.io.OnlineResource;
024
025/**
026 * The panel which displays the public discussion around a changeset in a scrollable table.
027 *
028 * It listens to property change events for {@link ChangesetCacheManagerModel#CHANGESET_IN_DETAIL_VIEW_PROP}
029 * and updates its view accordingly.
030 *
031 * @since 7704
032 */
033public class ChangesetDiscussionPanel extends JPanel implements PropertyChangeListener {
034
035    private final UpdateChangesetDiscussionAction actUpdateChangesets = new UpdateChangesetDiscussionAction();
036
037    private final ChangesetDiscussionTableModel model = new ChangesetDiscussionTableModel();
038
039    private JTable table;
040
041    private Changeset current = null;
042
043    protected JPanel buildActionButtonPanel() {
044        JPanel pnl = new JPanel(new FlowLayout(FlowLayout.LEFT));
045
046        JToolBar tb = new JToolBar(JToolBar.VERTICAL);
047        tb.setFloatable(false);
048
049        // -- changeset discussion update
050        tb.add(actUpdateChangesets);
051        actUpdateChangesets.initProperties(current);
052
053        pnl.add(tb);
054        return pnl;
055    }
056
057    /**
058     * Updates the current changeset discussion from the OSM server
059     */
060    class UpdateChangesetDiscussionAction extends AbstractAction {
061        public UpdateChangesetDiscussionAction() {
062            putValue(NAME, tr("Update changeset discussion"));
063            putValue(SMALL_ICON, ChangesetCacheManager.UPDATE_CONTENT_ICON);
064            putValue(SHORT_DESCRIPTION, tr("Update the changeset discussion from the OSM server"));
065        }
066
067        @Override
068        public void actionPerformed(ActionEvent evt) {
069            if (current == null) return;
070            Main.worker.submit(
071                    new ChangesetHeaderDownloadTask(
072                            ChangesetDiscussionPanel.this,
073                            Collections.singleton(current.getId()),
074                            true /* include discussion */
075                    )
076            );
077        }
078
079        public void initProperties(Changeset cs) {
080            setEnabled(cs != null && !Main.isOffline(OnlineResource.OSM_API));
081        }
082    }
083
084    /**
085     * Constructs a new {@code ChangesetDiscussionPanel}.
086     */
087    public ChangesetDiscussionPanel() {
088        build();
089    }
090
091    protected void setCurrentChangeset(Changeset cs) {
092        current = cs;
093        if (cs == null) {
094            clearView();
095        } else {
096            updateView(cs);
097        }
098        actUpdateChangesets.initProperties(current);
099        if (cs != null && cs.getDiscussion().size() < cs.getCommentsCount()) {
100            actUpdateChangesets.actionPerformed(null);
101        }
102    }
103
104    protected final void build() {
105        setLayout(new BorderLayout());
106        setBorder(BorderFactory.createEmptyBorder(3,3,3,3));
107        add(buildActionButtonPanel(), BorderLayout.WEST);
108        add(buildDiscussionPanel(), BorderLayout.CENTER);
109    }
110
111    private Component buildDiscussionPanel() {
112        JPanel pnl = new JPanel(new BorderLayout());
113        table = new JTable(model, new ChangesetDiscussionTableColumnModel());
114        pnl.add(new JScrollPane(table), BorderLayout.CENTER);
115        return pnl;
116    }
117
118    protected void clearView() {
119        model.populate(null);
120    }
121
122    protected void updateView(Changeset cs) {
123        model.populate(cs.getDiscussion());
124        // Update row heights
125        for (int row = 0; row < table.getRowCount(); row++) {
126            int rowHeight = table.getRowHeight();
127
128            Component comp = table.prepareRenderer(table.getCellRenderer(row, 2), row, 2);
129            rowHeight = Math.max(rowHeight, comp.getPreferredSize().height);
130
131            table.setRowHeight(row, rowHeight);
132        }
133    }
134
135    /* ---------------------------------------------------------------------------- */
136    /* interface PropertyChangeListener                                             */
137    /* ---------------------------------------------------------------------------- */
138    @Override
139    public void propertyChange(PropertyChangeEvent evt) {
140        if (! evt.getPropertyName().equals(ChangesetCacheManagerModel.CHANGESET_IN_DETAIL_VIEW_PROP))
141            return;
142        setCurrentChangeset((Changeset)evt.getNewValue());
143    }
144}