Ignore:
Timestamp:
2016-04-12T23:08:55+02:00 (8 years ago)
Author:
Don-vip
Message:

fix #12752 - Add more image filters (patch by michael2402, modified)

File:
1 edited

Legend:

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

    r10011 r10142  
    532532        protected static final int SLIDER_STEPS = 100;
    533533        private static final double MAX_GAMMA_FACTOR = 2;
     534        private static final double MAX_SHARPNESS_FACTOR = 2;
     535        private static final double MAX_COLORFUL_FACTOR = 2;
    534536        private final LayerListModel model;
    535537        private final JPopupMenu popup;
    536         private JSlider opacitySlider;
    537         private JSlider gammaSlider;
    538538        private SideButton sideButton;
    539539        private JCheckBox visibilityCheckbox;
     540        final OpacitySlider opacitySlider = new OpacitySlider();
     541        private final ArrayList<FilterSlider<?>> sliders = new ArrayList<>();
    540542
    541543        /**
     
    560562                @Override
    561563                public void stateChanged(ChangeEvent e) {
    562                     setVisible(visibilityCheckbox.isSelected());
     564                    setVisibleFlag(visibilityCheckbox.isSelected());
    563565                }
    564566            });
    565567            content.add(visibilityCheckbox, GBC.eop());
    566568
    567             content.add(new JLabel(ImageProvider.get("dialogs/layerlist", "transparency")), GBC.std().span(1, 2).insets(0, 0, 5, 0));
    568             content.add(new JLabel(tr("Opacity")), GBC.eol());
    569             opacitySlider = new JSlider(JSlider.HORIZONTAL);
    570             opacitySlider.setMaximum(SLIDER_STEPS);
    571             opacitySlider.addChangeListener(new ChangeListener() {
    572                 @Override
    573                 public void stateChanged(ChangeEvent e) {
    574                     setOpacityValue(readOpacityValue(), opacitySlider.getValueIsAdjusting());
    575                 }
    576             });
    577             opacitySlider.setToolTipText(tr("Adjust opacity of the layer."));
    578             content.add(opacitySlider, GBC.eop());
    579 
    580             content.add(new JLabel(ImageProvider.get("dialogs/layerlist", "gamma")), GBC.std().span(1, 2).insets(0, 0, 5, 0));
    581             content.add(new JLabel(tr("Gamma")), GBC.eol());
    582             gammaSlider = new JSlider(JSlider.HORIZONTAL);
    583             gammaSlider.setMaximum(SLIDER_STEPS);
    584             gammaSlider.addChangeListener(new ChangeListener() {
    585                 @Override
    586                 public void stateChanged(ChangeEvent e) {
    587                     setGammaValue(readGammaValue());
    588                 }
    589             });
    590             gammaSlider.setToolTipText(tr("Adjust gamma value of the layer."));
    591             content.add(gammaSlider, GBC.eol());
    592         }
    593 
    594         protected double readOpacityValue() {
    595             return (double) opacitySlider.getValue() / SLIDER_STEPS;
    596         }
    597 
    598         protected double readGammaValue() {
    599             return (double) gammaSlider.getValue() / SLIDER_STEPS * MAX_GAMMA_FACTOR;
    600         }
    601 
    602         protected void setVisible(boolean visible) {
     569            addSlider(content, opacitySlider);
     570            addSlider(content, new ColorfulnessSlider());
     571            addSlider(content, new GammaFilterSlider());
     572            addSlider(content, new SharpnessSlider());
     573        }
     574
     575        private void addSlider(JPanel content, FilterSlider<?> slider) {
     576            content.add(new JLabel(slider.getIcon()), GBC.std().span(1, 2).insets(0, 0, 5, 0));
     577            content.add(new JLabel(slider.getLabel()), GBC.eol());
     578            content.add(slider, GBC.eop());
     579            sliders.add(slider);
     580        }
     581
     582        protected void setVisibleFlag(boolean visible) {
    603583            for (Layer l : model.getSelectedLayers()) {
    604584                l.setVisible(visible);
    605585            }
    606586            updateValues();
    607         }
    608 
    609         protected void setOpacityValue(double value, boolean adjusting) {
    610             if (value <= 0 && !adjusting) {
    611                 setVisible(false);
    612             } else {
    613                 for (Layer l : model.getSelectedLayers()) {
    614                     l.setOpacity(value);
    615                 }
    616             }
    617         }
    618 
    619         protected void setGammaValue(double value) {
    620             for (ImageryLayer imageryLayer : Utils.filteredCollection(model.getSelectedLayers(), ImageryLayer.class)) {
    621                 imageryLayer.setGamma(value);
    622             }
    623587        }
    624588
     
    648612            visibilityCheckbox.setSelected(allVisible && !allHidden);
    649613
    650             updateOpacitySlider(layers, allHidden);
    651 
    652             updateGammaSlider(layers, allHidden);
    653         }
    654 
    655         private void updateGammaSlider(List<Layer> layers, boolean allHidden) {
    656             Collection<ImageryLayer> gammaLayers = Utils.filteredCollection(layers, ImageryLayer.class);
    657             if (gammaLayers.isEmpty() || allHidden) {
    658                 gammaSlider.setEnabled(false);
    659             } else {
    660                 gammaSlider.setEnabled(true);
    661                 double gamma = gammaLayers.iterator().next().getGamma();
    662                 gammaSlider.setValue((int) (gamma * SLIDER_STEPS / MAX_GAMMA_FACTOR));
    663             }
    664         }
    665 
    666         private void updateOpacitySlider(List<Layer> layers, boolean allHidden) {
    667             if (layers.isEmpty() || allHidden) {
    668                 opacitySlider.setEnabled(false);
    669             } else {
    670                 opacitySlider.setEnabled(true);
     614            for (FilterSlider<?> slider : sliders) {
     615                slider.updateSlider(layers, allHidden);
     616            }
     617        }
     618
     619        @Override
     620        public boolean supportLayers(List<Layer> layers) {
     621            return !layers.isEmpty();
     622        }
     623
     624        @Override
     625        public Component createMenuComponent() {
     626            return new JMenuItem(this);
     627        }
     628
     629        @Override
     630        public void updateEnabledState() {
     631            setEnabled(!model.getSelectedLayers().isEmpty());
     632        }
     633
     634        /**
     635         * Sets the corresponding side button.
     636         * @param sideButton the corresponding side button
     637         */
     638        void setCorrespondingSideButton(SideButton sideButton) {
     639            this.sideButton = sideButton;
     640        }
     641
     642        /**
     643         * This is a slider for a filter value.
     644         * @author Michael Zangl
     645         *
     646         * @param <T> The layer type.
     647         */
     648        private abstract class FilterSlider<T extends Layer> extends JSlider {
     649            private final double minValue;
     650            private final double maxValue;
     651            private final Class<T> layerClassFilter;
     652
     653            /**
     654             * Create a new filter slider.
     655             * @param minValue The minimum value to map to the left side.
     656             * @param maxValue The maximum value to map to the right side.
     657             * @param layerClassFilter The type of layer influenced by this filter.
     658             */
     659            FilterSlider(double minValue, double maxValue, Class<T> layerClassFilter) {
     660                super(JSlider.HORIZONTAL);
     661                this.minValue = minValue;
     662                this.maxValue = maxValue;
     663                this.layerClassFilter = layerClassFilter;
     664                setMaximum(SLIDER_STEPS);
     665                int tick = convertFromRealValue(1);
     666                setMinorTickSpacing(tick);
     667                setMajorTickSpacing(tick);
     668                setPaintTicks(true);
     669
     670                addChangeListener(new ChangeListener() {
     671                    @Override
     672                    public void stateChanged(ChangeEvent e) {
     673                        onStateChanged();
     674                    }
     675                });
     676            }
     677
     678            /**
     679             * Called whenever the state of the slider was changed.
     680             * @see #getValueIsAdjusting()
     681             * @see #getRealValue()
     682             */
     683            protected void onStateChanged() {
     684                Collection<T> layers = filterLayers(model.getSelectedLayers());
     685                for (T layer : layers) {
     686                    applyValueToLayer(layer);
     687                }
     688            }
     689
     690            protected void applyValueToLayer(T layer) {
     691            }
     692
     693            protected double getRealValue() {
     694                return convertToRealValue(getValue());
     695            }
     696
     697            protected double convertToRealValue(int value) {
     698                double s = (double) value / SLIDER_STEPS;
     699                return s * maxValue + (1-s) * minValue;
     700            }
     701
     702            protected void setRealValue(double value) {
     703                setValue(convertFromRealValue(value));
     704            }
     705
     706            protected int convertFromRealValue(double value) {
     707                int i = (int) ((value - minValue) / (maxValue - minValue) * SLIDER_STEPS + .5);
     708                if (i < getMinimum()) {
     709                    return getMinimum();
     710                } else if (i > getMaximum()) {
     711                    return getMaximum();
     712                } else {
     713                    return i;
     714                }
     715            }
     716
     717            public abstract ImageIcon getIcon();
     718
     719            public abstract String getLabel();
     720
     721            public void updateSlider(List<Layer> layers, boolean allHidden) {
     722                Collection<? extends Layer> usedLayers = filterLayers(layers);
     723                if (usedLayers.isEmpty() || allHidden) {
     724                    setEnabled(false);
     725                } else {
     726                    setEnabled(true);
     727                    updateSliderWhileEnabled(usedLayers, allHidden);
     728                }
     729            }
     730
     731            protected Collection<T> filterLayers(List<Layer> layers) {
     732                return Utils.filteredCollection(layers, layerClassFilter);
     733            }
     734
     735            protected abstract void updateSliderWhileEnabled(Collection<? extends Layer> usedLayers, boolean allHidden);
     736        }
     737
     738        /**
     739         * This slider allows you to change the opacity of a layer.
     740         *
     741         * @author Michael Zangl
     742         * @see Layer#setOpacity(double)
     743         */
     744        class OpacitySlider extends FilterSlider<Layer> {
     745            /**
     746             * Creaate a new {@link OpacitySlider}.
     747             */
     748            OpacitySlider() {
     749                super(0, 1, Layer.class);
     750                setToolTipText(tr("Adjust opacity of the layer."));
     751
     752            }
     753
     754            @Override
     755            protected void onStateChanged() {
     756                if (getRealValue() <= 0.001 && !getValueIsAdjusting()) {
     757                    setVisibleFlag(false);
     758                } else {
     759                    super.onStateChanged();
     760                }
     761            }
     762
     763            @Override
     764            protected void applyValueToLayer(Layer layer) {
     765                layer.setOpacity(getRealValue());
     766            }
     767
     768            @Override
     769            protected void updateSliderWhileEnabled(Collection<? extends Layer> usedLayers, boolean allHidden) {
    671770                double opacity = 0;
    672                 for (Layer l : layers) {
     771                for (Layer l : usedLayers) {
    673772                    opacity += l.getOpacity();
    674773                }
    675                 opacity /= layers.size();
     774                opacity /= usedLayers.size();
    676775                if (opacity == 0) {
    677776                    opacity = 1;
    678                     setOpacityValue(opacity, false);
    679                 }
    680                 opacitySlider.setValue((int) (opacity * SLIDER_STEPS));
    681             }
    682         }
    683 
    684         @Override
    685         public boolean supportLayers(List<Layer> layers) {
    686             return !layers.isEmpty();
    687         }
    688 
    689         @Override
    690         public Component createMenuComponent() {
    691             return new JMenuItem(this);
    692         }
    693 
    694         @Override
    695         public void updateEnabledState() {
    696             setEnabled(!model.getSelectedLayers().isEmpty());
    697         }
    698 
    699         /**
    700          * Sets the corresponding side button.
    701          * @param sideButton the corresponding side button
    702          */
    703         void setCorrespondingSideButton(SideButton sideButton) {
    704             this.sideButton = sideButton;
     777                    setVisibleFlag(true);
     778                }
     779                setRealValue(opacity);
     780            }
     781
     782            @Override
     783            public String getLabel() {
     784                return tr("Opacity");
     785            }
     786
     787            @Override
     788            public ImageIcon getIcon() {
     789                return ImageProvider.get("dialogs/layerlist", "transparency");
     790            }
     791
     792            @Override
     793            public String toString() {
     794                return "OpacitySlider [getRealValue()=" + getRealValue() + "]";
     795            }
     796        }
     797
     798        /**
     799         * This slider allows you to change the gamma value of a layer.
     800         *
     801         * @author Michael Zangl
     802         * @see ImageryLayer#setGamma(double)
     803         */
     804        private class GammaFilterSlider extends FilterSlider<ImageryLayer> {
     805
     806            /**
     807             * Create a new {@link GammaFilterSlider}
     808             */
     809            GammaFilterSlider() {
     810                super(0, MAX_GAMMA_FACTOR, ImageryLayer.class);
     811                setToolTipText(tr("Adjust gamma value of the layer."));
     812            }
     813
     814            @Override
     815            protected void updateSliderWhileEnabled(Collection<? extends Layer> usedLayers, boolean allHidden) {
     816                double gamma = ((ImageryLayer) usedLayers.iterator().next()).getGamma();
     817                setRealValue(gamma);
     818            }
     819
     820            @Override
     821            protected void applyValueToLayer(ImageryLayer layer) {
     822                layer.setGamma(getRealValue());
     823            }
     824
     825            @Override
     826            public ImageIcon getIcon() {
     827               return ImageProvider.get("dialogs/layerlist", "gamma");
     828            }
     829
     830            @Override
     831            public String getLabel() {
     832                return tr("Gamma");
     833            }
     834        }
     835
     836        /**
     837         * This slider allows you to change the sharpness of a layer.
     838         *
     839         * @author Michael Zangl
     840         * @see ImageryLayer#setSharpenLevel(double)
     841         */
     842        private class SharpnessSlider extends FilterSlider<ImageryLayer> {
     843
     844            /**
     845             * Creates a new {@link SharpnessSlider}
     846             */
     847            SharpnessSlider() {
     848                super(0, MAX_SHARPNESS_FACTOR, ImageryLayer.class);
     849                setToolTipText(tr("Adjust sharpness/blur value of the layer."));
     850            }
     851
     852            @Override
     853            protected void updateSliderWhileEnabled(Collection<? extends Layer> usedLayers, boolean allHidden) {
     854                setRealValue(((ImageryLayer) usedLayers.iterator().next()).getSharpenLevel());
     855            }
     856
     857            @Override
     858            protected void applyValueToLayer(ImageryLayer layer) {
     859                layer.setSharpenLevel(getRealValue());
     860            }
     861
     862            @Override
     863            public ImageIcon getIcon() {
     864               return ImageProvider.get("dialogs/layerlist", "sharpness");
     865            }
     866
     867            @Override
     868            public String getLabel() {
     869                return tr("Sharpness");
     870            }
     871        }
     872
     873        /**
     874         * This slider allows you to change the colorfulness of a layer.
     875         *
     876         * @author Michael Zangl
     877         * @see ImageryLayer#setColorfulness(double)
     878         */
     879        private class ColorfulnessSlider extends FilterSlider<ImageryLayer> {
     880
     881            /**
     882             * Create a new {@link ColorfulnessSlider}
     883             */
     884            ColorfulnessSlider() {
     885                super(0, MAX_COLORFUL_FACTOR, ImageryLayer.class);
     886                setToolTipText(tr("Adjust colorfulness of the layer."));
     887            }
     888
     889            @Override
     890            protected void updateSliderWhileEnabled(Collection<? extends Layer> usedLayers, boolean allHidden) {
     891                setRealValue(((ImageryLayer) usedLayers.iterator().next()).getColorfulness());
     892            }
     893
     894            @Override
     895            protected void applyValueToLayer(ImageryLayer layer) {
     896                layer.setColorfulness(getRealValue());
     897            }
     898
     899            @Override
     900            public ImageIcon getIcon() {
     901               return ImageProvider.get("dialogs/layerlist", "colorfulness");
     902            }
     903
     904            @Override
     905            public String getLabel() {
     906                return tr("Colorfulness");
     907            }
    705908        }
    706909    }
Note: See TracChangeset for help on using the changeset viewer.