package games.strategy.triplea.ui;
import java.awt.Cursor;
import java.awt.Image;
import java.awt.Point;
import java.awt.Toolkit;
import java.net.URL;
import java.util.Optional;
import java.util.logging.Level;
import java.util.prefs.BackingStoreException;
import java.util.prefs.Preferences;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import games.strategy.debug.ClientLogger;
import games.strategy.engine.data.GameData;
import games.strategy.engine.data.PlayerID;
import games.strategy.engine.data.UnitType;
import games.strategy.sound.ClipPlayer;
import games.strategy.triplea.ResourceLoader;
import games.strategy.triplea.image.DiceImageFactory;
import games.strategy.triplea.image.FlagIconImageFactory;
import games.strategy.triplea.image.MapImage;
import games.strategy.triplea.image.PUImageFactory;
import games.strategy.triplea.image.ResourceImageFactory;
import games.strategy.triplea.image.TileImageFactory;
import games.strategy.triplea.image.UnitImageFactory;
import games.strategy.triplea.ui.mapdata.MapData;
import games.strategy.triplea.ui.screen.drawable.IDrawable.OptionalExtraBorderLevel;
import games.strategy.triplea.util.Stopwatch;
/**
* A place to find images and map data for a ui.
*/
public class UIContext extends AbstractUIContext {
protected MapData m_mapData;
protected final TileImageFactory m_tileImageFactory = new TileImageFactory();
protected final UnitImageFactory m_unitImageFactory = new UnitImageFactory();
protected final ResourceImageFactory m_resourceImageFactory = new ResourceImageFactory();
protected final MapImage m_mapImage;
protected final FlagIconImageFactory m_flagIconImageFactory = new FlagIconImageFactory();
protected DiceImageFactory m_diceImageFactory;
protected final PUImageFactory m_PUImageFactory = new PUImageFactory();
protected boolean m_drawUnits = true;
protected boolean m_drawTerritoryEffects = false;
protected boolean m_drawMapOnly = false;
protected OptionalExtraBorderLevel m_extraTerritoryBorderLevel = OptionalExtraBorderLevel.LOW;
// protected final MainGameFrame m_frame;
protected Cursor m_cursor = Cursor.getDefaultCursor();
public UIContext() {
super();
m_mapImage = new MapImage();
// m_frame = frame;
}
@Override
public Cursor getCursor() {
return m_cursor;
}
@Override
public void setScale(final double scale) {
super.setScale(scale);
m_tileImageFactory.setScale(scale);
}
@Override
protected void internalSetMapDir(final String dir, final GameData data) {
final Stopwatch stopWatch = new Stopwatch(s_logger, Level.FINE, "Loading UI Context");
m_resourceLoader = ResourceLoader.getMapResourceLoader(dir);
if (m_mapData != null) {
m_mapData.close();
}
m_mapData = new MapData(m_resourceLoader);
// DiceImageFactory needs loader and game data
m_diceImageFactory = new DiceImageFactory(m_resourceLoader, data.getDiceSides());
final double unitScale = getPreferencesMapOrSkin(dir).getDouble(UNIT_SCALE_PREF, m_mapData.getDefaultUnitScale());
m_scale = getPreferencesMapOrSkin(dir).getDouble(MAP_SCALE_PREF, 1);
if (m_scale < 1) {
setDrawTerritoryBordersAgainToMedium();
}
m_unitImageFactory.setResourceLoader(m_resourceLoader, unitScale, m_mapData.getDefaultUnitWidth(),
m_mapData.getDefaultUnitHeight(), m_mapData.getDefaultUnitCounterOffsetWidth(),
m_mapData.getDefaultUnitCounterOffsetHeight());
// TODO: separate scale for resources
m_resourceImageFactory.setResourceLoader(m_resourceLoader, 1);
m_flagIconImageFactory.setResourceLoader(m_resourceLoader);
m_PUImageFactory.setResourceLoader(m_resourceLoader);
m_tileImageFactory.setMapDir(m_resourceLoader);
m_tileImageFactory.setScale(m_scale);
// load map data
m_mapImage.loadMaps(m_resourceLoader);
m_mapDir = dir;
m_drawTerritoryEffects = m_mapData.useTerritoryEffectMarkers();
// load the sounds in a background thread,
// avoids the pause where sounds dont load right away
final Runnable loadSounds = () -> {
// change the resource loader (this allows us to play sounds the map folder, rather than just default sounds)
ClipPlayer.getInstance(m_resourceLoader);
};
(new Thread(loadSounds, "Triplea sound loader")).start();
// load a new cursor
m_cursor = Cursor.getDefaultCursor();
final Toolkit toolkit = Toolkit.getDefaultToolkit();
// URL's use "/" not "\"
final URL cursorURL = m_resourceLoader.getResource("misc" + "/" + "cursor.gif");
if (cursorURL != null) {
try {
final Image image = ImageIO.read(cursorURL);
if (image != null) {
final Point hotSpot = new Point(m_mapData.getMapCursorHotspotX(), m_mapData.getMapCursorHotspotY());
m_cursor = toolkit.createCustomCursor(image, hotSpot, data.getGameName() + " Cursor");
}
} catch (final Exception e) {
ClientLogger.logQuietly(e);
}
}
stopWatch.done();
}
@Override
public MapData getMapData() {
return m_mapData;
}
@Override
public TileImageFactory getTileImageFactory() {
return m_tileImageFactory;
}
@Override
public UnitImageFactory getUnitImageFactory() {
return m_unitImageFactory;
}
@Override
public JLabel createUnitImageJLabel(final UnitType type, final PlayerID player, final GameData data,
final UnitDamage damaged, final UnitEnable disabled) {
final Optional<ImageIcon> image = getUnitImageFactory().getIcon(type, player, data, damaged == UnitDamage.DAMAGED,
disabled == UnitEnable.DISABLED);
if (image.isPresent()) {
return new JLabel(image.get());
} else {
return new JLabel();
}
}
@Override
public ResourceImageFactory getResourceImageFactory() {
return m_resourceImageFactory;
}
@Override
public MapImage getMapImage() {
return m_mapImage;
}
@Override
public FlagIconImageFactory getFlagImageFactory() {
return m_flagIconImageFactory;
}
@Override
public PUImageFactory getPUImageFactory() {
return m_PUImageFactory;
}
@Override
public DiceImageFactory getDiceImageFactory() {
return m_diceImageFactory;
}
@Override
public void shutDown() {
super.shutDown();
m_mapData.close();
}
@Override
public boolean getShowUnits() {
return m_drawUnits;
}
@Override
public void setShowUnits(final boolean aBool) {
m_drawUnits = aBool;
}
@Override
public OptionalExtraBorderLevel getDrawTerritoryBordersAgain() {
return m_extraTerritoryBorderLevel;
}
@Override
public void setDrawTerritoryBordersAgain(final OptionalExtraBorderLevel level) {
m_extraTerritoryBorderLevel = level;
}
@Override
public void resetDrawTerritoryBordersAgain() {
m_extraTerritoryBorderLevel = OptionalExtraBorderLevel.LOW;
}
@Override
public void setDrawTerritoryBordersAgainToMedium() {
m_extraTerritoryBorderLevel = OptionalExtraBorderLevel.MEDIUM;
}
@Override
public void setShowTerritoryEffects(final boolean aBool) {
m_drawTerritoryEffects = aBool;
}
@Override
public boolean getShowTerritoryEffects() {
return m_drawTerritoryEffects;
}
@Override
public boolean getShowMapOnly() {
return m_drawMapOnly;
}
@Override
public void setShowMapOnly(final boolean aBool) {
m_drawMapOnly = aBool;
}
@Override
public void setUnitScaleFactor(final double scaleFactor) {
m_unitImageFactory.setScaleFactor(scaleFactor);
final Preferences prefs = getPreferencesMapOrSkin(getMapDir());
prefs.putDouble(UNIT_SCALE_PREF, scaleFactor);
try {
prefs.flush();
} catch (final BackingStoreException e) {
ClientLogger.logQuietly(e);
}
}
}