001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.gui.preferences.imagery; 003 004import static org.openstreetmap.josm.tools.I18n.tr; 005 006import java.awt.Color; 007import java.awt.GridBagLayout; 008import java.io.File; 009import java.io.FilenameFilter; 010 011import javax.swing.JButton; 012import javax.swing.JColorChooser; 013import javax.swing.JLabel; 014import javax.swing.JOptionPane; 015import javax.swing.JPanel; 016import javax.swing.JSlider; 017import javax.swing.JSpinner; 018import javax.swing.SpinnerNumberModel; 019 020import org.openstreetmap.josm.data.cache.JCSCacheManager; 021import org.openstreetmap.josm.data.imagery.CachedTileLoaderFactory; 022import org.openstreetmap.josm.gui.layer.AbstractCachedTileSourceLayer; 023import org.openstreetmap.josm.gui.layer.AbstractTileSourceLayer; 024import org.openstreetmap.josm.gui.layer.ImageryLayer; 025import org.openstreetmap.josm.gui.widgets.JosmComboBox; 026import org.openstreetmap.josm.gui.widgets.JosmTextField; 027import org.openstreetmap.josm.tools.ColorHelper; 028import org.openstreetmap.josm.tools.GBC; 029import org.openstreetmap.josm.tools.Utils; 030 031/** 032 * {@code JPanel} giving access to common imagery settings. 033 * @since 5465 034 */ 035public class CommonSettingsPanel extends JPanel { 036 037 // Common Settings 038 private final JButton btnFadeColor; 039 private final JSlider fadeAmount = new JSlider(0, 100); 040 private final JosmComboBox<String> sharpen; 041 private final JosmTextField tilecacheDir = new JosmTextField(); 042 private final JSpinner maxElementsOnDisk; 043 private final JSlider tilesZoom = new JSlider(-2, 2, 0); 044 045 046 /** 047 * Constructs a new {@code CommonSettingsPanel}. 048 */ 049 public CommonSettingsPanel() { 050 super(new GridBagLayout()); 051 052 this.maxElementsOnDisk = new JSpinner(new SpinnerNumberModel( 053 AbstractCachedTileSourceLayer.MAX_DISK_CACHE_SIZE.get().intValue(), 0, Integer.MAX_VALUE, 1)); 054 055 this.btnFadeColor = new JButton(); 056 this.btnFadeColor.addActionListener(e -> { 057 JColorChooser chooser = new JColorChooser(btnFadeColor.getBackground()); 058 int answer = JOptionPane.showConfirmDialog( 059 this, chooser, 060 tr("Choose a color for {0}", tr("imagery fade")), 061 JOptionPane.OK_CANCEL_OPTION, 062 JOptionPane.PLAIN_MESSAGE); 063 if (answer == JOptionPane.OK_OPTION) { 064 Color colFadeColor = chooser.getColor(); 065 btnFadeColor.setBackground(colFadeColor); 066 btnFadeColor.setText(ColorHelper.color2html(colFadeColor)); 067 } 068 }); 069 070 add(new JLabel(tr("Fade Color: ")), GBC.std()); 071 add(GBC.glue(5, 0), GBC.std().fill(GBC.HORIZONTAL)); 072 add(this.btnFadeColor, GBC.eol().fill(GBC.HORIZONTAL)); 073 074 add(new JLabel(tr("Fade amount: ")), GBC.std()); 075 add(GBC.glue(5, 0), GBC.std().fill(GBC.HORIZONTAL)); 076 add(this.fadeAmount, GBC.eol().fill(GBC.HORIZONTAL)); 077 078 this.sharpen = new JosmComboBox<>(new String[] { 079 tr("None"), 080 tr("Soft"), 081 tr("Strong")}); 082 add(new JLabel(tr("Sharpen (requires layer re-add): "))); 083 add(GBC.glue(5, 0), GBC.std().fill(GBC.HORIZONTAL)); 084 add(this.sharpen, GBC.eol().fill(GBC.HORIZONTAL)); 085 086 add(new JLabel(tr("Tile cache directory: ")), GBC.std()); 087 add(GBC.glue(5, 0), GBC.std()); 088 add(tilecacheDir, GBC.eol().fill(GBC.HORIZONTAL)); 089 090 add(new JLabel(tr("Maximum size of disk cache (per imagery) in MB: ")), GBC.std()); 091 add(GBC.glue(5, 0), GBC.std()); 092 add(this.maxElementsOnDisk, GBC.eol()); 093 094 this.tilesZoom.setPaintLabels(true); 095 this.tilesZoom.setMajorTickSpacing(2); 096 this.tilesZoom.setMinorTickSpacing(1); 097 this.tilesZoom.setPaintTicks(true); 098 add(new JLabel(tr("Tiles zoom offset:"))); 099 add(GBC.glue(5, 0), GBC.std()); 100 add(this.tilesZoom, GBC.eol()); 101 } 102 103 /** 104 * Loads the common settings. 105 */ 106 public void loadSettings() { 107 Color colFadeColor = ImageryLayer.PROP_FADE_COLOR.get(); 108 this.btnFadeColor.setBackground(colFadeColor); 109 this.btnFadeColor.setText(ColorHelper.color2html(colFadeColor)); 110 this.fadeAmount.setValue(ImageryLayer.PROP_FADE_AMOUNT.get()); 111 this.sharpen.setSelectedIndex(Math.max(0, Math.min(2, ImageryLayer.PROP_SHARPEN_LEVEL.get()))); 112 this.tilecacheDir.setText(CachedTileLoaderFactory.PROP_TILECACHE_DIR.get()); 113 this.maxElementsOnDisk.setValue(AbstractCachedTileSourceLayer.MAX_DISK_CACHE_SIZE.get()); 114 this.tilesZoom.setValue(AbstractTileSourceLayer.ZOOM_OFFSET.get()); 115 } 116 117 /** 118 * Saves the common settings. 119 * @return true when restart is required 120 */ 121 public boolean saveSettings() { 122 ImageryLayer.PROP_FADE_AMOUNT.put(this.fadeAmount.getValue()); 123 ImageryLayer.PROP_FADE_COLOR.put(this.btnFadeColor.getBackground()); 124 ImageryLayer.PROP_SHARPEN_LEVEL.put(sharpen.getSelectedIndex()); 125 126 boolean restartRequired = false; 127 if (!AbstractCachedTileSourceLayer.MAX_DISK_CACHE_SIZE.get().equals(this.maxElementsOnDisk.getValue())) { 128 if (((Integer) this.maxElementsOnDisk.getValue()) < AbstractCachedTileSourceLayer.MAX_DISK_CACHE_SIZE.get() && 129 JCSCacheManager.USE_BLOCK_CACHE.get()) { 130 // reducing size of the cache, this requires deletion of the files 131 removeCacheFiles(CachedTileLoaderFactory.PROP_TILECACHE_DIR.get()); 132 } 133 AbstractCachedTileSourceLayer.MAX_DISK_CACHE_SIZE.put((Integer) this.maxElementsOnDisk.getValue()); 134 restartRequired = true; 135 } 136 137 138 if (!CachedTileLoaderFactory.PROP_TILECACHE_DIR.get().equals(this.tilecacheDir.getText())) { 139 restartRequired = true; 140 removeCacheFiles(CachedTileLoaderFactory.PROP_TILECACHE_DIR.get()); // clear old cache directory 141 CachedTileLoaderFactory.PROP_TILECACHE_DIR.put(this.tilecacheDir.getText()); 142 } 143 144 if (!AbstractTileSourceLayer.ZOOM_OFFSET.get().equals(this.tilesZoom.getValue())) { 145 // TODO: make warning about too small MEMORY_CACHE_SIZE? 146 AbstractTileSourceLayer.ZOOM_OFFSET.put(this.tilesZoom.getValue()); 147 restartRequired = true; 148 } 149 return restartRequired; 150 } 151 152 private void removeCacheFiles(String path) { 153 File directory = new File(path); 154 File[] cacheFiles = directory.listFiles((FilenameFilter) (dir, name) -> name.endsWith(".data") || name.endsWith(".key")); 155 JCSCacheManager.shutdown(); // shutdown Cache - so files can by safely deleted 156 for (File cacheFile: cacheFiles) { 157 Utils.deleteFile(cacheFile); 158 } 159 } 160}