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.GridBagLayout; 007import java.io.File; 008import java.io.FilenameFilter; 009 010import javax.swing.JLabel; 011import javax.swing.JPanel; 012import javax.swing.JSlider; 013import javax.swing.JSpinner; 014import javax.swing.SpinnerNumberModel; 015 016import org.openstreetmap.josm.data.cache.JCSCacheManager; 017import org.openstreetmap.josm.data.imagery.CachedTileLoaderFactory; 018import org.openstreetmap.josm.gui.layer.AbstractCachedTileSourceLayer; 019import org.openstreetmap.josm.gui.layer.AbstractTileSourceLayer; 020import org.openstreetmap.josm.gui.layer.ImageryLayer; 021import org.openstreetmap.josm.gui.widgets.JosmComboBox; 022import org.openstreetmap.josm.gui.widgets.JosmTextField; 023import org.openstreetmap.josm.tools.GBC; 024import org.openstreetmap.josm.tools.Utils; 025 026/** 027 * {@code JPanel} giving access to common imagery settings. 028 * @since 5465 029 */ 030public class CommonSettingsPanel extends JPanel { 031 032 // Common Settings 033 private final JosmComboBox<String> sharpen; 034 private final JosmTextField tilecacheDir = new JosmTextField(11); 035 private final JSpinner maxElementsOnDisk; 036 private final JSlider tilesZoom = new JSlider(-2, 2, 0); 037 038 039 /** 040 * Constructs a new {@code CommonSettingsPanel}. 041 */ 042 public CommonSettingsPanel() { 043 super(new GridBagLayout()); 044 045 this.maxElementsOnDisk = new JSpinner(new SpinnerNumberModel( 046 AbstractCachedTileSourceLayer.MAX_DISK_CACHE_SIZE.get().intValue(), 0, Integer.MAX_VALUE, 1)); 047 048 this.sharpen = new JosmComboBox<>(new String[] { 049 tr("None"), 050 tr("Soft"), 051 tr("Strong")}); 052 add(new JLabel(tr("Sharpen (requires layer re-add): "))); 053 add(GBC.glue(5, 0), GBC.std().fill(GBC.HORIZONTAL)); 054 add(this.sharpen, GBC.eol().fill(GBC.HORIZONTAL)); 055 056 add(new JLabel(tr("Tile cache directory: ")), GBC.std()); 057 add(GBC.glue(5, 0), GBC.std()); 058 add(tilecacheDir, GBC.eol().fill(GBC.HORIZONTAL)); 059 060 add(new JLabel(tr("Maximum size of disk cache (per imagery) in MB: ")), GBC.std()); 061 add(GBC.glue(5, 0), GBC.std()); 062 add(this.maxElementsOnDisk, GBC.eol()); 063 064 this.tilesZoom.setPaintLabels(true); 065 this.tilesZoom.setMajorTickSpacing(2); 066 this.tilesZoom.setMinorTickSpacing(1); 067 this.tilesZoom.setPaintTicks(true); 068 add(new JLabel(tr("Tiles zoom offset:"))); 069 add(GBC.glue(5, 0), GBC.std()); 070 add(this.tilesZoom, GBC.eol()); 071 } 072 073 /** 074 * Loads the common settings. 075 */ 076 public void loadSettings() { 077 this.sharpen.setSelectedIndex(Utils.clamp(ImageryLayer.PROP_SHARPEN_LEVEL.get(), 0, 2)); 078 this.tilecacheDir.setText(CachedTileLoaderFactory.PROP_TILECACHE_DIR.get()); 079 this.maxElementsOnDisk.setValue(AbstractCachedTileSourceLayer.MAX_DISK_CACHE_SIZE.get()); 080 this.tilesZoom.setValue(AbstractTileSourceLayer.ZOOM_OFFSET.get()); 081 } 082 083 /** 084 * Saves the common settings. 085 * @return true when restart is required 086 */ 087 public boolean saveSettings() { 088 ImageryLayer.PROP_SHARPEN_LEVEL.put(sharpen.getSelectedIndex()); 089 090 boolean restartRequired = false; 091 if (!AbstractCachedTileSourceLayer.MAX_DISK_CACHE_SIZE.get().equals(this.maxElementsOnDisk.getValue())) { 092 if (((Integer) this.maxElementsOnDisk.getValue()) < AbstractCachedTileSourceLayer.MAX_DISK_CACHE_SIZE.get() && 093 JCSCacheManager.USE_BLOCK_CACHE.get()) { 094 // reducing size of the cache, this requires deletion of the files 095 removeCacheFiles(CachedTileLoaderFactory.PROP_TILECACHE_DIR.get()); 096 } 097 AbstractCachedTileSourceLayer.MAX_DISK_CACHE_SIZE.put((Integer) this.maxElementsOnDisk.getValue()); 098 restartRequired = true; 099 } 100 101 102 if (!CachedTileLoaderFactory.PROP_TILECACHE_DIR.get().equals(this.tilecacheDir.getText())) { 103 restartRequired = true; 104 removeCacheFiles(CachedTileLoaderFactory.PROP_TILECACHE_DIR.get()); // clear old cache directory 105 CachedTileLoaderFactory.PROP_TILECACHE_DIR.put(this.tilecacheDir.getText()); 106 } 107 108 if (!AbstractTileSourceLayer.ZOOM_OFFSET.get().equals(this.tilesZoom.getValue())) { 109 // TODO: make warning about too small MEMORY_CACHE_SIZE? 110 AbstractTileSourceLayer.ZOOM_OFFSET.put(this.tilesZoom.getValue()); 111 restartRequired = true; 112 } 113 return restartRequired; 114 } 115 116 private static void removeCacheFiles(String path) { 117 File directory = new File(path); 118 File[] cacheFiles = directory.listFiles((FilenameFilter) (dir, name) -> name.endsWith(".data") || name.endsWith(".key")); 119 JCSCacheManager.shutdown(); // shutdown Cache - so files can by safely deleted 120 if (cacheFiles != null) { 121 for (File cacheFile: cacheFiles) { 122 Utils.deleteFile(cacheFile); 123 } 124 } 125 } 126}