001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.download;
003
004import java.awt.Component;
005import java.util.function.IntSupplier;
006
007import org.openstreetmap.josm.data.preferences.AbstractProperty;
008
009/**
010 * Defines the sizing policy used for download tabs.
011 * @author Michael Zangl
012 * @since 12705
013 */
014public interface DownloadSourceSizingPolicy {
015    /**
016     * Gets the height of the download source panel.
017     * @return The height the component should have.
018     */
019    int getComponentHeight();
020
021    /**
022     * Check whether the user should be allowed to adjust the height of this download source panel
023     * @return <code>true</code> if the height should be adjustable
024     */
025    boolean isHeightAdjustable();
026
027    /**
028     * Stores the height
029     * @param height the height in pixel
030     */
031    default void storeHeight(int height) {
032        throw new UnsupportedOperationException(
033                "Setting the height is not supported for " + this.getClass().getCanonicalName());
034    }
035
036    /**
037     * The download source has a fixed size provided by the component
038     * @author Michael Zangl
039     */
040    class FixedDownloadSourceSizePolicy implements DownloadSourceSizingPolicy {
041        private final Component base;
042
043        /**
044         * Create a new fixed download source policy
045         * @param base The component of which the size should be taken.
046         */
047        public FixedDownloadSourceSizePolicy(Component base) {
048            this.base = base;
049        }
050
051        @Override
052        public int getComponentHeight() {
053            return (int) base.getPreferredSize().getHeight();
054        }
055
056        @Override
057        public boolean isHeightAdjustable() {
058            return false;
059        }
060    }
061
062    /**
063     * The height of this component is given by a preference entry.
064     * <p>
065     * Mind that using a preferred component size is not possible in this case,
066     * since the preference entry needs to have a constant default value.
067     */
068    class AdjustableDownloadSizePolicy implements DownloadSourceSizingPolicy {
069
070        private final AbstractProperty<Integer> preference;
071        private final IntSupplier minHeight;
072
073        /**
074         * Create a new {@link AdjustableDownloadSizePolicy}
075         * @param preference The preference to use
076         */
077        public AdjustableDownloadSizePolicy(AbstractProperty<Integer> preference) {
078            this(preference, () -> 1);
079        }
080
081        /**
082         * Create a new {@link AdjustableDownloadSizePolicy}
083         * @param preference The preference to use
084         * @param minHeight A supplier that gives the minimum height of the component. Must be positive or 0.
085         * @since 14418
086         */
087        public AdjustableDownloadSizePolicy(AbstractProperty<Integer> preference, IntSupplier minHeight) {
088            this.preference = preference;
089            this.minHeight = minHeight;
090        }
091
092        @Override
093        public int getComponentHeight() {
094            int computedMinHeight = this.minHeight.getAsInt();
095            if (computedMinHeight < 0) {
096                throw new IllegalStateException("Illegal minimum component height:" + computedMinHeight);
097            }
098            return Math.max(computedMinHeight, preference.get());
099        }
100
101        @Override
102        public boolean isHeightAdjustable() {
103            return true;
104        }
105
106        @Override
107        public void storeHeight(int height) {
108            preference.put(height);
109        }
110
111    }
112}