/*******************************************************************************
* Copyright (c) MOBAC developers
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package mobac.gui.settings;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.LinkedList;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.SwingUtilities;
import javax.swing.border.BevelBorder;
import mobac.mapsources.MapSourcesManager;
import mobac.program.interfaces.MapSource;
import mobac.program.tilestore.TileStore;
import mobac.program.tilestore.TileStoreInfo;
import mobac.program.tilestore.berkeleydb.DelayedInterruptThread;
import mobac.utilities.I18nUtils;
import mobac.utilities.Utilities;
public class SettingsGUITileStore extends JPanel {
public final JCheckBox tileStoreEnabled;
private final JPanel tileStoreInfoPanel;
private List<TileSourceInfoComponents> tileStoreInfoList = new LinkedList<TileSourceInfoComponents>();
private JLabel totalTileCountLabel;
private JLabel totalTileSizeLabel;
protected DelayedInterruptThread tileStoreAsyncThread = null;
public SettingsGUITileStore(SettingsGUI gui) {
super();
gui.addTab(I18nUtils.localizedStringForKey("set_tile_store_title"), this);
tileStoreEnabled = new JCheckBox(I18nUtils.localizedStringForKey("set_tile_store_enable_checkbox"));
JPanel tileStorePanel = new JPanel(new BorderLayout());
tileStorePanel.setBorder(SettingsGUI.createSectionBorder(I18nUtils.localizedStringForKey("set_tile_store_settings")));
tileStorePanel.add(tileStoreEnabled, BorderLayout.CENTER);
tileStoreInfoPanel = new JPanel(new GridBagLayout());
// tileStoreInfoPanel.setBorder(createSectionBorder("Information"));
prepareTileStoreInfoPanel();
setLayout(new BorderLayout());
add(tileStorePanel, BorderLayout.NORTH);
JScrollPane scrollPane = new JScrollPane(tileStoreInfoPanel, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
tileStoreInfoPanel.setMinimumSize(new Dimension(200, 300));
// scrollPane.setMinimumSize(new Dimension(100, 100));
scrollPane.setPreferredSize(new Dimension(520, 100));
scrollPane.setBorder(SettingsGUI.createSectionBorder(I18nUtils.localizedStringForKey("set_tile_store_information")));
add(scrollPane, BorderLayout.CENTER);
}
/**
*
* @param updateStoreName
* name of the tile store to update or <code>null</code> in case of all tile stores to be updated
*/
private void updateTileStoreInfoPanel(String updateStoreName) {
try {
TileStore tileStore = TileStore.getInstance();
long totalTileCount = 0;
long totalTileSize = 0;
for (final TileSourceInfoComponents info : tileStoreInfoList) {
String storeName = info.name;
Utilities.checkForInterruption();
int count;
long size;
if (updateStoreName == null || info.name.equals(updateStoreName)) {
TileStoreInfo tsi = tileStore.getStoreInfo(storeName);
count = tsi.getTileCount();
size = tsi.getStoreSize();
info.count = count;
info.size = size;
final String mapTileCountText = (count < 0) ? "??" : Integer.toString(count);
final String mapTileSizeText = Utilities.formatBytes(size);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
info.countLabel.setText("<html><b>" + mapTileCountText + "</b></html>");
info.sizeLabel.setText("<html><b>" + mapTileSizeText + "</b></html>");
}
});
} else {
count = info.count;
size = info.size;
}
totalTileCount += count;
totalTileSize += size;
}
final String totalTileCountText = "<html><b>" + Long.toString(totalTileCount) + "</b></html>";
final String totalTileSizeText = "<html><b>" + Utilities.formatBytes(totalTileSize) + "</b></html>";
SwingUtilities.invokeLater(new Runnable() {
public void run() {
totalTileCountLabel.setText(totalTileCountText);
totalTileSizeLabel.setText(totalTileSizeText);
}
});
} catch (InterruptedException e) {
SettingsGUI.log.debug("Tile store information retrieval was canceled");
}
}
synchronized void updateTileStoreInfoPanelAsync(final String storeName) {
if (tileStoreAsyncThread != null)
return; // An update is currently running
tileStoreAsyncThread = new DelayedInterruptThread("TileStoreInfoRetriever") {
@Override
public void run() {
if (storeName == null)
SettingsGUI.log.debug("Updating tilestore information in background");
else
SettingsGUI.log.debug("Updating tilestore information for \"" + storeName + "\" in background");
updateTileStoreInfoPanel(storeName);
SettingsGUI.log.debug("Updating tilestore information finished");
tileStoreAsyncThread = null;
}
};
tileStoreAsyncThread.start();
}
private void prepareTileStoreInfoPanel() {
final GridBagConstraints gbc_mapSource = new GridBagConstraints();
gbc_mapSource.insets = new Insets(5, 10, 5, 10);
gbc_mapSource.anchor = GridBagConstraints.WEST;
final GridBagConstraints gbc_mapTiles = new GridBagConstraints();
gbc_mapTiles.insets = gbc_mapSource.insets;
gbc_mapTiles.anchor = GridBagConstraints.EAST;
final GridBagConstraints gbc_eol = new GridBagConstraints();
gbc_eol.gridwidth = GridBagConstraints.REMAINDER;
TileStore tileStore = TileStore.getInstance();
MapSourcesManager mapSourcesManager = MapSourcesManager.getInstance();
tileStoreInfoPanel.add(new JLabel(I18nUtils.localizedStringForKey("set_tile_store_info_mapsrc")), gbc_mapSource);
tileStoreInfoPanel.add(new JLabel(I18nUtils.localizedStringForKey("set_tile_store_info_tiles")), gbc_mapTiles);
tileStoreInfoPanel.add(new JLabel(I18nUtils.localizedStringForKey("set_tile_store_info_size")), gbc_eol);
ImageIcon trash = Utilities.loadResourceImageIcon("trash.png");
for (String name : tileStore.getAllStoreNames()) {
String mapTileCountText = " ? ";
String mapTileSizeText = " ? ";
MapSource mapSource = mapSourcesManager.getSourceByName(name);
final JLabel mapSourceNameLabel;
if (mapSource != null)
mapSourceNameLabel = new JLabel(name);
else
mapSourceNameLabel = new JLabel(name + I18nUtils.localizedStringForKey("set_tile_store_info_disabled_subfix"));
final JLabel mapTileCountLabel = new JLabel(mapTileCountText);
final JLabel mapTileSizeLabel = new JLabel(mapTileSizeText);
final JButton deleteButton = new JButton(trash);
TileSourceInfoComponents info = new TileSourceInfoComponents();
info.name = name;
info.countLabel = mapTileCountLabel;
info.sizeLabel = mapTileSizeLabel;
tileStoreInfoList.add(info);
deleteButton.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
deleteButton.setToolTipText(String.format(I18nUtils.localizedStringForKey("set_tile_store_info_delete_tips"), name));
deleteButton.addActionListener(new ClearTileCacheAction(name));
tileStoreInfoPanel.add(mapSourceNameLabel, gbc_mapSource);
tileStoreInfoPanel.add(mapTileCountLabel, gbc_mapTiles);
tileStoreInfoPanel.add(mapTileSizeLabel, gbc_mapTiles);
tileStoreInfoPanel.add(deleteButton, gbc_eol);
}
JSeparator hr = new JSeparator(JSeparator.HORIZONTAL);
hr.setBorder(BorderFactory.createEtchedBorder(BevelBorder.LOWERED));
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.fill = GridBagConstraints.HORIZONTAL;
tileStoreInfoPanel.add(hr, gbc);
JLabel totalMapLabel = new JLabel(I18nUtils.localizedStringForKey("set_tile_store_info_total"));
totalTileCountLabel = new JLabel("<html><b>??</b></html>");
totalTileSizeLabel = new JLabel("<html><b>??</b></html>");
tileStoreInfoPanel.add(totalMapLabel, gbc_mapSource);
tileStoreInfoPanel.add(totalTileCountLabel, gbc_mapTiles);
tileStoreInfoPanel.add(totalTileSizeLabel, gbc_mapTiles);
}
public void stopThread() {
Thread t = tileStoreAsyncThread;
if (t != null)
t.interrupt();
}
private static class TileSourceInfoComponents {
JLabel sizeLabel;
JLabel countLabel;
String name;
int count = -1;
long size = 0;
}
private class ClearTileCacheAction implements ActionListener {
String storeName;
public ClearTileCacheAction(String storeName) {
this.storeName = storeName;
}
public void actionPerformed(ActionEvent e) {
final JButton b = (JButton) e.getSource();
b.setEnabled(false);
b.setToolTipText(I18nUtils.localizedStringForKey("set_tile_store_info_deleteing_tips"));
Thread t = new DelayedInterruptThread("TileStore_" + storeName + "_DeleteThread") {
@Override
public void run() {
try {
TileStore ts = TileStore.getInstance();
ts.clearStore(storeName);
SettingsGUITileStore.this.updateTileStoreInfoPanelAsync(storeName);
SettingsGUITileStore.this.repaint();
} catch (Exception e) {
SettingsGUI.log.error("An error occured while cleaning tile cache: ", e);
}
}
};
t.start();
}
}
}