Changeset 3705 in josm


Ignore:
Timestamp:
2010-12-07T12:21:47+01:00 (10 years ago)
Author:
Upliner
Message:

applied #5570 - implement layer opacity control

Location:
trunk
Files:
2 added
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/gui/MapView.java

    r3675 r3705  
    44import static org.openstreetmap.josm.tools.I18n.tr;
    55
     6import java.awt.AlphaComposite;
    67import java.awt.Color;
    78import java.awt.Graphics;
     
    184185    // Layers that wasn't changed since last paint
    185186    private final List<Layer> nonChangedLayers = new ArrayList<Layer>();
     187    private Layer changedLayer;
    186188    private int lastViewID;
    187189    private boolean paintPreferencesChanged = true;
     
    440442    }
    441443
     444    private void paintLayer(Layer layer, Graphics2D g, Bounds box) {
     445        if (layer.getOpacity() < 1) {
     446            g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,(float)layer.getOpacity()));
     447        }
     448        layer.paint(g, this, box);
     449        g.setPaintMode();
     450    }
     451
    442452    /**
    443453     * Draw the component.
     
    454464        int nonChangedLayersCount = 0;
    455465        for (Layer l: visibleLayers) {
    456             if (l.isChanged()) {
     466            if (l.isChanged() || l == changedLayer) {
    457467                break;
    458468            } else {
     
    490500
    491501            for (int i=0; i<nonChangedLayersCount; i++) {
    492                 visibleLayers.get(i).paint(g2, this, box);
     502                paintLayer(visibleLayers.get(i),g2, box);
    493503            }
    494504        } else {
     
    498508                g2.setClip(g.getClip());
    499509                for (int i=nonChangedLayers.size(); i<nonChangedLayersCount; i++) {
    500                     visibleLayers.get(i).paint(g2, this, box);
     510                    paintLayer(visibleLayers.get(i),g2, box);
    501511                }
    502512            }
     
    504514
    505515        nonChangedLayers.clear();
     516        changedLayer = null;
    506517        for (int i=0; i<nonChangedLayersCount; i++) {
    507518            nonChangedLayers.add(visibleLayers.get(i));
     
    514525
    515526        for (int i=nonChangedLayersCount; i<visibleLayers.size(); i++) {
    516             visibleLayers.get(i).paint(tempG, this, box);
     527            paintLayer(visibleLayers.get(i),tempG, box);
    517528        }
    518529
     
    783794        if (evt.getPropertyName().equals(Layer.VISIBLE_PROP)) {
    784795            repaint();
     796        } else if (evt.getPropertyName().equals(Layer.OPACITY_PROP)) {
     797            Layer l = (Layer)evt.getSource();
     798            if (l.isVisible()) {
     799                changedLayer = l;
     800                repaint();
     801            }
    785802        } else if (evt.getPropertyName().equals(OsmDataLayer.REQUIRES_SAVE_TO_DISK_PROP)
    786803                || evt.getPropertyName().equals(OsmDataLayer.REQUIRES_UPLOAD_TO_SERVER_PROP)) {
  • trunk/src/org/openstreetmap/josm/gui/dialogs/LayerListDialog.java

    r3689 r3705  
    3131import javax.swing.JMenuItem;
    3232import javax.swing.JPanel;
     33import javax.swing.JPopupMenu;
    3334import javax.swing.JScrollPane;
     35import javax.swing.JSlider;
    3436import javax.swing.JTable;
    3537import javax.swing.JTextField;
     
    3840import javax.swing.ListSelectionModel;
    3941import javax.swing.UIManager;
     42import javax.swing.event.ChangeEvent;
     43import javax.swing.event.ChangeListener;
    4044import javax.swing.event.ListSelectionEvent;
    4145import javax.swing.event.ListSelectionListener;
     
    108112    private LayerList layerList;
    109113
     114    private SideButton opacityButton;
     115
    110116    ActivateLayerAction activateLayerAction;
    111117
     
    152158        adaptTo(deleteLayerAction, selectionModel);
    153159        buttonPanel.add(new SideButton(deleteLayerAction, false));
     160
     161        //-- layer opacity action
     162        LayerOpacityAction layerOpacityAction = new LayerOpacityAction();
     163        adaptTo(layerOpacityAction, selectionModel);
     164        opacityButton = new SideButton(layerOpacityAction);
     165        buttonPanel.add(opacityButton);
    154166
    155167        return buttonPanel;
     
    185197        layerList.getColumnModel().getColumn(0).setResizable(false);
    186198        layerList.getColumnModel().getColumn(1).setCellRenderer(new LayerVisibleCellRenderer());
    187         layerList.getColumnModel().getColumn(1).setCellEditor(new DefaultCellEditor(new LayerVisibleCheckBox()));
     199        layerList.getColumnModel().getColumn(1).setCellEditor(new LayerVisibleCellEditor(new LayerVisibleCheckBox()));
    188200        layerList.getColumnModel().getColumn(1).setMaxWidth(16);
    189201        layerList.getColumnModel().getColumn(1).setPreferredWidth(16);
     
    200212                KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_UP, 0),
    201213                KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_DOWN, 0),
    202                 })
     214        })
    203215        {
    204216            layerList.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(ks, new Object());
     
    279291    protected void adaptTo(final IEnabledStateUpdating listener, LayerListModel listModel) {
    280292        listModel.addTableModelListener(
    281             new TableModelListener() {
    282 
    283                 @Override
    284                 public void tableChanged(TableModelEvent e) {
    285                     listener.updateEnabledState();
    286                 }
    287             }
     293                new TableModelListener() {
     294
     295                    @Override
     296                    public void tableChanged(TableModelEvent e) {
     297                        listener.updateEnabledState();
     298                    }
     299                }
    288300        );
    289301    }
     
    438450        public boolean equals(Object obj) {
    439451            return obj instanceof ShowHideLayerAction;
     452        }
     453
     454        @Override
     455        public int hashCode() {
     456            return getClass().hashCode();
     457        }
     458    }
     459
     460    public final class LayerOpacityAction extends AbstractAction implements IEnabledStateUpdating, LayerAction {
     461        private Layer layer;
     462        private JPopupMenu popup;
     463        private JSlider slider = new JSlider(JSlider.VERTICAL);
     464
     465        /**
     466         * Creates a {@see LayerOpacityAction} which allows to chenge the
     467         * opacity of one or more layers.
     468         *
     469         * @param layer  the layer. Must not be null.
     470         * @exception IllegalArgumentException thrown, if layer is null
     471         */
     472        public LayerOpacityAction(Layer layer) throws IllegalArgumentException {
     473            this();
     474            putValue(NAME, tr("Opacity"));
     475            CheckParameterUtil.ensureParameterNotNull(layer, "layer");
     476            this.layer = layer;
     477            updateEnabledState();
     478        }
     479
     480        /**
     481         * Creates a {@see ShowHideLayerAction} which will toggle the visibility of
     482         * the currently selected layers
     483         *
     484         */
     485        public LayerOpacityAction() {
     486            putValue(SHORT_DESCRIPTION, tr("Adjust opacity of the layer."));
     487            putValue(SMALL_ICON, ImageProvider.get("dialogs/layerlist", "transparency"));
     488            updateEnabledState();
     489
     490            popup = new JPopupMenu();
     491            slider.addChangeListener(new ChangeListener() {
     492                @Override
     493                public void stateChanged(ChangeEvent e) {
     494                    setOpacity((double)slider.getValue()/100);
     495                }
     496            });
     497            popup.add(slider);
     498        }
     499
     500        private void setOpacity(double value) {
     501            if (!isEnabled()) return;
     502            if (layer != null) {
     503                layer.setOpacity(value);
     504            } else {
     505                for(Layer layer: model.getSelectedLayers()) {
     506                    layer.setOpacity(value);
     507                }
     508            }
     509        }
     510
     511        private double getOpacity() {
     512            if (layer != null)
     513                return layer.getOpacity();
     514            else {
     515                double opacity = 0;
     516                List<Layer> layers = model.getSelectedLayers();
     517                for(Layer layer: layers) {
     518                    opacity += layer.getOpacity();
     519                }
     520                return opacity / layers.size();
     521            }
     522        }
     523
     524        @Override
     525        public void actionPerformed(ActionEvent e) {
     526            slider.setValue((int)Math.round(getOpacity()*100));
     527            popup.show(opacityButton, 0, opacityButton.getHeight());
     528        }
     529
     530        @Override
     531        public void updateEnabledState() {
     532            if (layer == null) {
     533                setEnabled(! getModel().getSelectedLayers().isEmpty());
     534            } else {
     535                setEnabled(true);
     536            }
     537        }
     538
     539        @Override
     540        public Component createMenuComponent() {
     541            return new JMenuItem(this);
     542        }
     543
     544        @Override
     545        public boolean supportLayers(List<Layer> layers) {
     546            return true;
     547        }
     548
     549        @Override
     550        public boolean equals(Object obj) {
     551            return obj instanceof LayerOpacityAction;
    440552        }
    441553
     
    635747
    636748    private static class LayerVisibleCheckBox extends JCheckBox {
     749        private final ImageIcon icon_eye;
     750        private final ImageIcon icon_eye_translucent;
     751        private boolean isTranslucent;
    637752        public LayerVisibleCheckBox() {
    638753            setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
    639             ImageIcon eye = ImageProvider.get("dialogs/layerlist", "eye");
    640             ImageIcon eye_off = ImageProvider.get("dialogs/layerlist", "eye-off");
    641             setIcon(eye_off);
    642             setSelectedIcon(eye);
    643             setRolloverIcon(eye_off);
    644             setRolloverSelectedIcon(eye);
     754            icon_eye = ImageProvider.get("dialogs/layerlist", "eye");
     755            icon_eye_translucent = ImageProvider.get("dialogs/layerlist", "eye-translucent");
     756            setIcon(ImageProvider.get("dialogs/layerlist", "eye-off"));
    645757            setPressedIcon(ImageProvider.get("dialogs/layerlist", "eye-pressed"));
     758            setSelectedIcon(icon_eye);
     759            isTranslucent = false;
     760        }
     761
     762        public void setTranslucent(boolean isTranslucent) {
     763            if (this.isTranslucent == isTranslucent) return;
     764            if (isTranslucent) {
     765                setSelectedIcon(icon_eye_translucent);
     766            } else {
     767                setSelectedIcon(icon_eye);
     768            }
     769            this.isTranslucent = isTranslucent;
     770        }
     771
     772        public void updateStatus(Layer layer) {
     773            boolean visible = layer.isVisible();
     774            setSelected(visible);
     775            setTranslucent(layer.getOpacity()<1.0);
     776            setToolTipText(visible ? tr("layer is currently visible (click to hide layer)") : tr("layer is currently hidden (click to show layer)"));
    646777        }
    647778    }
     
    663794
    664795    private static class LayerVisibleCellRenderer implements TableCellRenderer {
    665         JCheckBox cb;
     796        LayerVisibleCheckBox cb;
    666797        public LayerVisibleCellRenderer() {
    667             cb = new LayerVisibleCheckBox();
     798            this.cb = new LayerVisibleCheckBox();
    668799        }
    669800
    670801        @Override
    671802        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
    672             boolean visible = (Boolean) value;
    673             cb.setSelected(visible);
    674             cb.setToolTipText(visible ? tr("layer is currently visible (click to hide layer)") : tr("layer is currently hidden (click to show layer)"));
     803            cb.updateStatus((Layer)value);
    675804            return cb;
    676805        }
    677806    }
    678807
    679    private static class LayerNameCellRenderer extends DefaultTableCellRenderer {
     808    private static class LayerVisibleCellEditor extends DefaultCellEditor {
     809        LayerVisibleCheckBox cb;
     810        public LayerVisibleCellEditor(LayerVisibleCheckBox cb) {
     811            super(cb);
     812            this.cb = cb;
     813        }
     814
     815        @Override
     816        public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
     817            cb.updateStatus((Layer)value);
     818            return cb;
     819        }
     820    }
     821
     822    private static class LayerNameCellRenderer extends DefaultTableCellRenderer {
    680823
    681824        protected boolean isActiveLayer(Layer layer) {
     
    11421285            switch (col) {
    11431286            case 0: return getLayers().get(row) == getActiveLayer();
    1144             case 1: return getLayers().get(row).isVisible();
     1287            case 1: return getLayers().get(row);
    11451288            case 2: return getLayers().get(row);
    11461289            default: throw new RuntimeException();
     
    11691312                l.setName((String) value);
    11701313                break;
    1171                 default: throw new RuntimeException();
     1314            default: throw new RuntimeException();
    11721315            }
    11731316            fireTableCellUpdated(row, col);
  • trunk/src/org/openstreetmap/josm/gui/layer/Layer.java

    r3408 r3705  
    7070
    7171    static public final String VISIBLE_PROP = Layer.class.getName() + ".visible";
     72    static public final String OPACITY_PROP = Layer.class.getName() + ".opacity";
    7273    static public final String NAME_PROP = Layer.class.getName() + ".name";
    7374
     
    8182     */
    8283    private boolean visible = true;
     84
     85    /**
     86     * The opacity of the layer.
     87     *
     88     */
     89    private double opacity = 1;
    8390
    8491    /**
     
    111118     * @param mv The object that can translate GeoPoints to screen coordinates.
    112119     */
     120    @Override
    113121    abstract public void paint(Graphics2D g, MapView mv, Bounds box);
    114122    /**
     
    160168     * via command line parameter).
    161169     */
     170    @Override
    162171    public void destroy() {}
    163172
     
    216225     */
    217226    public void setVisible(boolean visible) {
    218         boolean oldValue = this.visible;
     227        boolean oldValue = isVisible();
    219228        this.visible  = visible;
    220         if (oldValue != this.visible) {
    221             fireVisibleChanged(oldValue, this.visible);
     229        if (visible && opacity == 0) {
     230            setOpacity(1);
     231        } else if (oldValue != isVisible()) {
     232            fireVisibleChanged(oldValue, isVisible());
    222233        }
    223234    }
     
    228239     */
    229240    public boolean isVisible() {
    230         return visible;
     241        return visible && opacity != 0;
     242    }
     243
     244    public double getOpacity() {
     245        return opacity;
     246    }
     247
     248    public void setOpacity(double opacity) {
     249        if (!(opacity >= 0 && opacity <= 1))
     250            throw new IllegalArgumentException("Opacity value must be between 0 and 1");
     251        double oldOpacity = getOpacity();
     252        boolean oldVisible = isVisible();
     253        this.opacity = opacity;
     254        if (oldOpacity != getOpacity()) {
     255            fireOpacityChanged(oldOpacity, getOpacity());
     256        }
     257        if (oldVisible != isVisible()) {
     258            fireVisibleChanged(oldVisible, isVisible());
     259        }
    231260    }
    232261
     
    264293    protected void fireVisibleChanged(boolean oldValue, boolean newValue) {
    265294        propertyChangeSupport.firePropertyChange(VISIBLE_PROP, oldValue, newValue);
     295    }
     296
     297    /**
     298     * fires a property change for the property {@see #OPACITY_PROP}
     299     *
     300     * @param oldValue the old value
     301     * @param newValue the new value
     302     */
     303    protected void fireOpacityChanged(double oldValue, double newValue) {
     304        propertyChangeSupport.firePropertyChange(OPACITY_PROP, oldValue, newValue);
    266305    }
    267306
Note: See TracChangeset for help on using the changeset viewer.