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, since the preference entry needs to have a onstant default value.
066     */
067    class AdjustableDownloadSizePolicy implements DownloadSourceSizingPolicy {
068
069        private final AbstractProperty<Integer> preference;
070        private IntSupplier minHeight;
071
072        /**
073         * Create a new {@link AdjustableDownloadSizePolicy}
074         * @param preference The preference to use
075         */
076        public AdjustableDownloadSizePolicy(AbstractProperty<Integer> preference) {
077            this(preference, () -> 1);
078        }
079
080        /**
081         * Create a new {@link AdjustableDownloadSizePolicy}
082         * @param preference The preference to use
083         * @param minHeight A supplier that gives the minimum height of the component. Must be positive or 0.
084         * @since 14418
085         */
086        public AdjustableDownloadSizePolicy(AbstractProperty<Integer> preference, IntSupplier minHeight) {
087            this.preference = preference;
088            this.minHeight = minHeight;
089        }
090
091        @Override
092        public int getComponentHeight() {
093            int computedMinHeight = this.minHeight.getAsInt();
094            if (computedMinHeight < 0) {
095                throw new IllegalStateException("Illegal minimum component height:" + computedMinHeight);
096            }
097            return Math.max(computedMinHeight, preference.get());
098        }
099
100        @Override
101        public boolean isHeightAdjustable() {
102            return true;
103        }
104
105        @Override
106        public void storeHeight(int height) {
107            preference.put(height);
108        }
109
110    }
111}