/** * Copyright (C) 2002-2012 The FreeCol Team * * This file is part of FreeCol. * * FreeCol 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. * * FreeCol 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 FreeCol. If not, see <http://www.gnu.org/licenses/>. */ package net.sf.freecol.client.gui; import java.awt.Component; import java.awt.Dimension; import java.awt.Graphics2D; import java.awt.GraphicsDevice; import java.awt.GraphicsEnvironment; import java.awt.Image; import java.awt.Point; import java.awt.Rectangle; import java.awt.Toolkit; import java.awt.image.BufferedImage; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.File; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.ImageIcon; import javax.swing.JLabel; import javax.swing.JMenuBar; import javax.swing.JWindow; import javax.swing.SwingUtilities; import javax.swing.filechooser.FileFilter; import net.sf.freecol.client.ClientOptions; import net.sf.freecol.client.FreeColClient; import net.sf.freecol.client.gui.Canvas.BoycottAction; import net.sf.freecol.client.gui.Canvas.BuyAction; import net.sf.freecol.client.gui.Canvas.ClaimAction; import net.sf.freecol.client.gui.Canvas.EventType; import net.sf.freecol.client.gui.Canvas.MissionaryAction; import net.sf.freecol.client.gui.Canvas.ScoutColonyAction; import net.sf.freecol.client.gui.Canvas.ScoutIndianSettlementAction; import net.sf.freecol.client.gui.Canvas.SellAction; import net.sf.freecol.client.gui.Canvas.TradeAction; import net.sf.freecol.client.gui.animation.Animations; import net.sf.freecol.client.gui.i18n.Messages; import net.sf.freecol.client.gui.menu.FreeColMenuBar; import net.sf.freecol.client.gui.menu.InGameMenuBar; import net.sf.freecol.client.gui.menu.MapEditorMenuBar; import net.sf.freecol.client.gui.panel.ChoiceItem; import net.sf.freecol.client.gui.panel.ColonyPanel; import net.sf.freecol.client.gui.panel.CornerMapControls; import net.sf.freecol.client.gui.panel.EuropePanel; import net.sf.freecol.client.gui.panel.MiniMap; import net.sf.freecol.client.gui.panel.LabourData.UnitData; import net.sf.freecol.client.gui.panel.LoadingSavegameDialog; import net.sf.freecol.client.gui.panel.MapControls; import net.sf.freecol.client.gui.panel.Parameters; import net.sf.freecol.client.gui.sound.SoundPlayer; import net.sf.freecol.common.ServerInfo; import net.sf.freecol.common.model.Colony; import net.sf.freecol.common.model.DiplomaticTrade; import net.sf.freecol.common.model.Europe; import net.sf.freecol.common.model.FoundingFather; import net.sf.freecol.common.model.FreeColGameObject; import net.sf.freecol.common.model.FreeColObject; import net.sf.freecol.common.model.Game; import net.sf.freecol.common.model.Goods; import net.sf.freecol.common.model.GoodsType; import net.sf.freecol.common.model.IndianSettlement; import net.sf.freecol.common.model.Location; import net.sf.freecol.common.model.ModelMessage; import net.sf.freecol.common.model.Monarch.MonarchAction; import net.sf.freecol.common.model.PathNode; import net.sf.freecol.common.model.Player; import net.sf.freecol.common.model.Settlement; import net.sf.freecol.common.model.Specification; import net.sf.freecol.common.model.StringTemplate; import net.sf.freecol.common.model.Tile; import net.sf.freecol.common.model.TradeRoute; import net.sf.freecol.common.model.TypeCountMap; import net.sf.freecol.common.model.Unit; import net.sf.freecol.common.model.UnitType; import net.sf.freecol.common.option.AudioMixerOption; import net.sf.freecol.common.option.BooleanOption; import net.sf.freecol.common.option.LanguageOption; import net.sf.freecol.common.option.LanguageOption.Language; import net.sf.freecol.common.option.Option; import net.sf.freecol.common.option.OptionGroup; import net.sf.freecol.common.option.PercentageOption; import net.sf.freecol.common.resources.ResourceManager; public class GUI { private static final Logger logger = Logger.getLogger(GUI.class.getName()); public static final String COPYRIGHT = "Copyright (C) 2002-2012 The FreeCol Team"; public static final String LICENSE = "http://www.gnu.org/licenses/gpl.html"; public static final String REVISION = "$Revision$"; /** * The space not being used in windowed mode. */ private static final int DEFAULT_WINDOW_SPACE = 50; public static final int MOVE_UNITS_MODE = 0; public static final int VIEW_TERRAIN_MODE = 1; private FreeColClient freeColClient; private GraphicsDevice gd; private FreeColFrame frame; private Canvas canvas; private MapViewer mapViewer; private MapControls mapControls; /** * This is the MapViewer instance used to paint the colony tiles in the * ColonyPanel and other panels. It should not be scaled along * with the default MapViewer. */ private MapViewer colonyTileGUI; private ImageLibrary imageLibrary; private SoundPlayer soundPlayer; private boolean windowed; private Rectangle windowBounds; private JWindow splash; public GUI(FreeColClient freeColClient) { this.freeColClient = freeColClient; this.imageLibrary = new ImageLibrary(); } public void activateGotoPath() { Unit unit = getActiveUnit(); // Action should be disabled if there is no active unit, but make sure if (unit == null) return; // Enter "goto mode" if not already activated; otherwise cancel it if (mapViewer.isGotoStarted()) { mapViewer.stopGoto(); } else { mapViewer.startGoto(); // Draw the path to the current mouse position, if the // mouse is over the screen; see also // CanvaseMouseMotionListener Point pt = canvas.getMousePosition(); if (pt != null) { Tile tile = mapViewer.convertToMapTile(pt.x, pt.y); if (tile != null && unit.getTile() != tile) { mapViewer.setGotoPath(unit.findPath(tile)); } } } } /** * Verifies if the client can play sounds. * @return boolean <b>true</b> if and only if client sound player has an instance */ public boolean canPlaySound() { return soundPlayer != null; } public void centerActiveUnit() { mapViewer.centerActiveUnit(); } /** * Change the windowed mode. * @param windowed Use <code>true</code> for windowed mode * and <code>false</code> for fullscreen mode. */ public void changeWindowedMode(boolean windowed) { JMenuBar menuBar = null; if (frame != null) { menuBar = frame.getJMenuBar(); if (frame instanceof WindowedFrame) { this.windowBounds = frame.getBounds(); } frame.setVisible(false); frame.dispose(); } setWindowed(windowed); this.frame = FreeColFrame.createFreeColFrame(freeColClient, canvas, gd, windowed); frame.setJMenuBar(menuBar); frame.setCanvas(canvas); frame.updateBounds(getWindowBounds()); mapViewer.forceReposition(); canvas.updateSizes(); frame.setVisible(true); } public void closeMainPanel() { canvas.closeMainPanel(); } public void closeMenus() { canvas.closeMenus(); } public void closeStatusPanel() { canvas.closeStatusPanel(); } public boolean containsInGameComponents() { return canvas.containsInGameComponents(); } public Dimension determineWindowSize() { Rectangle bounds = GraphicsEnvironment.getLocalGraphicsEnvironment() .getMaximumWindowBounds(); Dimension size = new Dimension(bounds.width - DEFAULT_WINDOW_SPACE, bounds.height - DEFAULT_WINDOW_SPACE); return size; } public void displayChat(String senderNme, String message, boolean privateChat) { canvas.displayChat(senderNme, message, privateChat); } /** * Tells the map controls that a chat message was received. * * @param player The player who sent the chat message. * @param message The chat message. * @param privateChat 'true' if the message is a private one, 'false' * otherwise. * @see GUIMessage */ public void displayChatMessage(Player player, String message, boolean privateChat) { mapViewer.addMessage(new GUIMessage(player.getName() + ": " + message, imageLibrary.getColor(player))); canvas.repaint(0, 0, canvas.getWidth(), canvas.getHeight()); } public void displaySpashScreen(final String splashFilename) { splash = null; if (splashFilename != null) { try { Image im = Toolkit.getDefaultToolkit() .getImage(splashFilename); splash = new JWindow(); splash.getContentPane().add(new JLabel(new ImageIcon(im))); splash.pack(); Point center = GraphicsEnvironment .getLocalGraphicsEnvironment().getCenterPoint(); splash.setLocation(center.x - splash.getWidth() / 2, center.y - splash.getHeight() / 2); splash.setVisible(true); } catch (Exception e) { logger.log(Level.WARNING, "Splash fail", e); splash = null; } } } public void errorMessage(String messageId) { canvas.errorMessage(messageId); } public void errorMessage(String messageID, String message) { canvas.errorMessage(messageID, message); } public void executeWithUnitOutForAnimation(final Unit unit, final Tile sourceTile, final OutForAnimationCallback r) { mapViewer.executeWithUnitOutForAnimation(unit, sourceTile, r); } public Unit getActiveUnit() { if (mapViewer == null) return null; return mapViewer.getActiveUnit(); } public Canvas getCanvas() { return canvas; } public MapViewer getColonyTileGUI() { return colonyTileGUI; } public int getCurrentViewMode() { return mapViewer.getView(); } public Tile getFocus() { if (mapViewer == null) return null; return mapViewer.getFocus(); } public ImageIcon getImageIcon(Object display, boolean small) { return imageLibrary.getImageIcon(display, small); } public ImageLibrary getImageLibrary() { return imageLibrary; } public LoadingSavegameDialog getLoadingSavegameDialog() { return canvas.getLoadingSavegameDialog(); } public float getMapScale() { return mapViewer.getMapScale(); } public MapViewer getMapViewer() { return mapViewer; } public Tile getSelectedTile() { return mapViewer.getSelectedTile(); } public SoundPlayer getSoundPlayer() { return soundPlayer; } public Rectangle getTileBounds(Tile tile) { return mapViewer.getTileBounds(tile); } public Point getTilePosition(Tile tile) { return mapViewer.getTilePosition(tile); } public Rectangle getWindowBounds() { return windowBounds; } public void hideSplashScreen() { if (splash != null) { splash.setVisible(false); splash.dispose(); } } public boolean isClientOptionsDialogShowing() { return canvas != null && !canvas.isClientOptionsDialogShowing(); } public boolean isMapboardActionsEnabled() { return canvas != null && canvas.isMapboardActionsEnabled(); } public boolean isShowingSubPanel() { return canvas.isShowingSubPanel(); } public boolean isWindowed() { return windowed; } public boolean onScreen(Tile tileToCheck) { return mapViewer.onScreen(tileToCheck); } public void paintImmediatelyCanvasIn(Rectangle rectangle) { canvas.paintImmediately(rectangle); } public void paintImmediatelyCanvasInItsBounds() { canvas.paintImmediately(canvas.getBounds()); } /** * Plays some sound. Parameter == null stops playing a sound. * * @param sound The sound resource to play or <b>null</b> */ public void playSound(String sound) { if (canPlaySound()) { if (sound == null) { soundPlayer.stop(); } else { File file = ResourceManager.getAudio(sound); if (file != null) { soundPlayer.playOnce(file); } logger.finest(((file == null) ? "Could not load" : "Playing") + " sound: " + sound); } } } public void quit() throws Exception { if (!isWindowed()) { gd.setFullScreenWindow(null); } } public void refresh() { mapViewer.forceReposition(); canvas.refresh(); } public void refreshPlayersTable() { canvas.refreshPlayersTable(); } /** * Refreshes the screen at the specified Tile. * * @param t The tile to refresh. */ public void refreshTile(Tile t) { if (t.getX() >= 0 && t.getY() >= 0) { canvas.repaint(mapViewer.getTileBounds(t)); } } public void removeFromCanvas(Component component) { canvas.remove(component); } public void removeInGameComponents() { canvas.removeInGameComponents(); } public void requestFocusForSubPanel() { canvas.getShowingSubPanel().requestFocus(); } public boolean requestFocusInWindow() { return canvas.requestFocusInWindow(); } public void resetMenuBar() { JMenuBar menuBar = frame.getJMenuBar(); if (menuBar != null) { ((FreeColMenuBar) menuBar).reset(); } } public void returnToTitle() { canvas.returnToTitle(); } public void scaleMap(float delta) { mapViewer.scaleMap(delta); refresh(); } public void setActiveUnit(Unit unitToActivate) { mapViewer.setActiveUnit(unitToActivate); } public void setFocus(Tile tileToFocus) { mapViewer.setFocus(tileToFocus); } public void setFocusImmediately(Tile tileToFocus) { mapViewer.setFocusImmediately(tileToFocus); } public boolean setSelectedTile(Tile newTileToSelect, boolean clearGoToOrders) { return mapViewer.setSelectedTile(newTileToSelect, clearGoToOrders); } public void setupInGameMenuBar() { frame.setJMenuBar(new InGameMenuBar(freeColClient, this)); frame.paintAll(canvas.getGraphics()); } public void setupMenuBarToNull() { frame.setJMenuBar(null); } public void setUpMouseListenersForCanvas(){ canvas.addMouseListener(new CanvasMouseListener(freeColClient, canvas, mapViewer)); canvas.addMouseMotionListener(new CanvasMouseMotionListener(freeColClient, mapViewer)); } public void setWindowed(boolean windowed) { this.windowed = windowed; } public void showAboutPanel() { canvas.showAboutPanel(); } public ScoutIndianSettlementAction showArmedUnitIndianSettlementDialog(IndianSettlement settlement) { return canvas.showArmedUnitIndianSettlementDialog(settlement); } public BoycottAction showBoycottedGoodsDialog(Goods goods, Europe europe) { return canvas.showBoycottedGoodsDialog(goods, europe); } public void showBuildQueuePanel(Colony colony) { canvas.showBuildQueuePanel(colony); } public void showBuildQueuePanel(Colony colony, Runnable callBack) { canvas.showBuildQueuePanel(colony, callBack); } public BuyAction showBuyDialog(Unit unit, Settlement settlement, Goods goods, int gold, boolean canBuy) { return canvas.showBuyDialog(unit, settlement, goods, gold, canBuy); } public List<Goods> showCaptureGoodsDialog(Unit winner, List<Goods> loot) { return canvas.showCaptureGoodsDialog(winner, loot); } public void showChatPanel() { canvas.showChatPanel(); } public <T> T showChoiceDialog(Tile tile, String text, String cancelText, List<ChoiceItem<T>> choices) { return canvas.showChoiceDialog(tile, text, cancelText, choices); } public MonarchAction showChoiceMonarchActionDialog(String monarchTitle, List<ChoiceItem<MonarchAction>> actions) { return canvas.showChoiceMonarchActionDialog(monarchTitle, actions); } public FoundingFather showChooseFoundingFatherDialog(List<ChoiceItem<FoundingFather>> fathers, String fatherTitle) { return canvas.showChooseFoundingFatherDialog(fathers, fatherTitle); } public FoundingFather showChooseFoundingFatherDialog(List<FoundingFather> ffs) { return canvas.showChooseFoundingFatherDialog(ffs); } public ClaimAction showClaimDialog(Tile tile, Player player, int price, Player owner, boolean canAccept) { return canvas.showClaimDialog(tile, player, price, owner, canAccept); } public OptionGroup showClientOptionsDialog() { return canvas.showClientOptionsDialog(); } public ColonyPanel showColonyPanel(Colony colony) { return canvas.showColonyPanel(colony); } public void showColonyPanel(Colony colony, Runnable callback) { canvas.showColonyPanel(colony, callback); } public void showColopediaPanel(String nodeId) { canvas.showColopediaPanel(nodeId); } public void showCompactLabourReport() { canvas.showCompactLabourReport(); } public void showCompactLabourReport(UnitData unitData) { canvas.showCompactLabourReport(unitData); } public List<String> showConfirmDeclarationDialog() { return canvas.showConfirmDeclarationDialog(); } public boolean showConfirmDialog(String text, String okText, String cancelText) { return canvas.showConfirmDialog(text, okText, cancelText); } public boolean showConfirmDialog(Tile tile, ModelMessage[] messages, String okText, String cancelText) { return canvas.showConfirmDialog(tile, messages, okText, cancelText); } public boolean showConfirmDialog(Tile tile, StringTemplate text, String okText, String cancelText) { return canvas.showConfirmDialog(tile, text, okText, cancelText); } public void showDeclarationDialog() { canvas.showDeclarationDialog(); } public void showDifficultyDialog(boolean editable) { canvas.showDifficultyDialog(editable); } public OptionGroup showDifficultyDialog(Specification specification) { return canvas.showDifficultyDialog(specification); } public List<Goods> showDumpCargoDialog(Unit unit) { return canvas.showDumpCargoDialog(unit); } public boolean showEditOptionDialog(Option option) { return canvas.showEditOptionDialog(option); } public int showEmigrationPanel(boolean fountainOfYouth) { return canvas.showEmigrationPanel(fountainOfYouth); } public boolean showEndTurnDialog(List<Unit> units) { return canvas.showEndTurnDialog(units); } public int showEuropeDialog(EuropePanel.EuropeAction europeAction) { return canvas.showEuropeDialog(europeAction); } public void showEuropePanel() { canvas.showEuropePanel(); } public void showEventPanel(EventType type) { canvas.showEventPanel(type); } public void showFindSettlementDialog() { canvas.showFindSettlementDialog(); } public void showGameOptionsDialog(boolean editable, boolean loadCustomOptions) { canvas.showGameOptionsDialog(editable, loadCustomOptions); } public void showHighScoresPanel(String messageId) { canvas.showHighScoresPanel(messageId); } public void showIndianSettlementPanel(IndianSettlement indianSettlement) { canvas.showIndianSettlementPanel(indianSettlement); } public TradeAction showIndianSettlementTradeDialog(Settlement settlement, boolean canBuy, boolean canSell, boolean canGift) { return canvas.showIndianSettlementTradeDialog(settlement, canBuy, canSell, canGift); } public void showInformationMessage(FreeColObject displayObject, String messageId) { canvas.showInformationMessage(displayObject, messageId); } public void showInformationMessage(FreeColObject displayObject, StringTemplate template) { canvas.showInformationMessage(displayObject, template); } public void showInformationMessage(ModelMessage message) { canvas.showInformationMessage(message); } public void showInformationMessage(String messageId) { canvas.showInformationMessage(messageId); } public void showInformationMessage(StringTemplate template) { canvas.showInformationMessage(template); } public String showInputDialog(Tile tile, StringTemplate text, String defaultValue, String okText, String cancelText, boolean rejectEmptyString) { return canvas.showInputDialog(tile, text, defaultValue, okText, cancelText, rejectEmptyString); } public File showLoadDialog(File directory) { return canvas.showLoadDialog(directory); } public File showLoadDialog(File directory, FileFilter[] fileFilters) { return canvas.showLoadDialog(directory, fileFilters); } public boolean showLoadingSavegameDialog(boolean publicServer, boolean singlePlayer) { return canvas.showLoadingSavegameDialog(publicServer, singlePlayer); } public void showLogFilePanel() { canvas.showLogFilePanel(); } public void showMainPanel() { canvas.showMainPanel(); } public OptionGroup showMapGeneratorOptionsDialog(OptionGroup mgo, boolean editable, boolean loadCustomOptions){ return canvas.showMapGeneratorOptionsDialog(mgo, editable, loadCustomOptions); } public Dimension showMapSizeDialog() { return canvas.showMapSizeDialog(); } public void showModelMessages(ModelMessage... modelMessages) { canvas.showModelMessages(modelMessages); } public boolean showMonarchPanelDialog(MonarchAction action, StringTemplate replace) { return canvas.showMonarchPanelDialog(action, replace); } public DiplomaticTrade showNegotiationDialog(Unit unit, Settlement settlement, DiplomaticTrade agreement) { return canvas.showNegotiationDialog(unit, settlement, agreement); } public void showNewPanel() { canvas.showNewPanel(); } public void showNewPanel(Specification specification) { canvas.showNewPanel(specification); } public boolean showPreCombatDialog(FreeColGameObject attacker, FreeColGameObject defender, Tile tile) { return canvas.showPreCombatDialog(attacker, defender, tile); } public void showReportCargoPanel() { canvas.showReportCargoPanel(); } public void showReportColonyPanel() { canvas.showReportColonyPanel(); } public void showReportContinentalCongressPanel() { canvas.showReportContinentalCongressPanel(); } public void showReportEducationPanel() { canvas.showReportEducationPanel(); } public void showReportExplorationPanel() { canvas.showReportExplorationPanel(); } public void showReportForeignAffairPanel() { canvas.showReportForeignAffairPanel(); } public void showReportHistoryPanel() { canvas.showReportHistoryPanel(); } public void showReportIndianPanel() { canvas.showReportIndianPanel(); } public void showReportLabourDetailPanel(UnitType unitType, Map<UnitType, Map<Location, Integer>> data, TypeCountMap<UnitType> unitCount, List<Colony> colonies) { canvas.showReportLabourDetailPanel(unitType, data, unitCount, colonies); } public void showReportLabourPanel() { canvas.showReportLabourPanel(); } public void showReportMilitaryPanel() { canvas.showReportMilitaryPanel(); } public void showReportNavalPanel() { canvas.showReportNavalPanel(); } public void showReportProductionPanel() { canvas.showReportProductionPanel(); } public void showReportReligiousPanel() { canvas.showReportReligiousPanel(); } public void showReportRequirementsPanel() { canvas.showReportRequirementsPanel(); } public void showReportTradePanel() { canvas.showReportTradePanel(); } public void showReportTurnPanel(ModelMessage... messages) { canvas.showReportTurnPanel(messages); } public File showSaveDialog(File directory, String defaultName) { return canvas.showSaveDialog(directory, defaultName); } public File showSaveDialog(File directory, String standardName, FileFilter[] fileFilters, String defaultName) { return canvas.showSaveDialog(directory, standardName, fileFilters, defaultName); } public ScoutColonyAction showScoutForeignColonyDialog(Colony colony, Unit unit, boolean canNegotiate) { return canvas.showScoutForeignColonyDialog(colony, unit, canNegotiate); } public ScoutIndianSettlementAction showScoutIndianSettlementDialog(IndianSettlement settlement, String number) { return canvas.showScoutIndianSettlementDialog(settlement, number); } public int showSelectAmountDialog(GoodsType goodsType, int available, int defaultAmount, boolean needToPay) { return canvas.showSelectAmountDialog(goodsType, available, defaultAmount, needToPay); } public Location showSelectDestinationDialog(Unit unit) { return canvas.showSelectDestinationDialog(unit); } public SellAction showSellDialog(Unit unit, Settlement settlement, Goods goods, int gold) { return canvas.showSellDialog(unit, settlement, goods, gold); } public void showServerListPanel(String username, List<ServerInfo> serverList) { canvas.showServerListPanel(username, serverList); } public <T> T showSimpleChoiceDialog(Tile tile, String text, String cancelText, List<T> objects) { return canvas.showSimpleChoiceDialog(tile, text, cancelText, objects); } public void showStartGamePanel(Game game, Player player, boolean singlePlayerMode) { canvas.showStartGamePanel(game, player, singlePlayerMode); } public void showStatisticsPanel() { canvas.showStatisticsPanel(); } public void showStatusPanel(String message) { canvas.showStatusPanel(message); } public void showTilePanel(Tile tile) { canvas.showTilePanel(tile); } public void showTilePopUpAtSelectedTile() { canvas.showTilePopup(getSelectedTile(), mapViewer.getCursor().getCanvasX(), mapViewer.getCursor().getCanvasY()); } public boolean showTradeRouteDialog(Unit unit) { return canvas.showTradeRouteDialog(unit); } public boolean showTradeRouteInputDialog(TradeRoute newRoute) { return canvas.showTradeRouteInputDialog(newRoute); } public MissionaryAction showUseMissionaryDialog(Unit unit, IndianSettlement settlement, boolean canEstablish, boolean canDenounce) { return canvas.showUseMissionaryDialog(unit, settlement, canEstablish, canDenounce); } public void showVictoryPanel() { canvas.showVictoryPanel(); } public boolean showWarehouseDialog(Colony colony) { return canvas.showWarehouseDialog(colony); } public void showWorkProductionPanel(Unit unit) { canvas.showWorkProductionPanel(unit); } /** * Starts the GUI by creating and displaying the GUI-objects. */ public void startGUI(Dimension innerWindowSize, final boolean sound, final boolean showOpeningVideo, final boolean loadGame) { final ClientOptions opts = freeColClient.getClientOptions(); // Prepare the sound system. if (sound) { final AudioMixerOption amo = (AudioMixerOption) opts.getOption(ClientOptions.AUDIO_MIXER); final PercentageOption volume = (PercentageOption) opts.getOption(ClientOptions.AUDIO_VOLUME); try { this.soundPlayer = new SoundPlayer(amo, volume); } catch (Exception e) { // #3168279 reports an undocumented NPE thrown by // AudioSystem.getMixer(null). Workaround this and other // such failures by just disabling sound. this.soundPlayer = null; logger.log(Level.WARNING, "Sound disabled", e); } } else { this.soundPlayer = null; } if (GraphicsEnvironment.isHeadless()) { logger.info("It seems that the GraphicsEnvironment is headless!"); } this.gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice(); if (!isWindowed()) { if (!gd.isFullScreenSupported()) { String fullscreenNotSupported = "\nIt seems that full screen mode is not fully supported for this" + "\nGraphicsDevice. Please try the \"--windowed\" option if you\nexperience" + "any graphical problems while running FreeCol."; logger.info(fullscreenNotSupported); System.out.println(fullscreenNotSupported); /* * We might want this behavior later: logger.warning("It seems * that full screen mode is not supported for this * GraphicsDevice! Using windowed mode instead."); windowed = * true; setWindowed(true); frame = new * WindowedFrame(size); */ } Rectangle bounds = gd.getDefaultConfiguration().getBounds(); innerWindowSize = new Dimension(bounds.width - bounds.x, bounds.height - bounds.y); } // Work around a Java 2D bug that seems to be X11 specific. // According to: // http://www.oracle.com/technetwork/java/javase/index-142560.html // // ``The use of pixmaps typically results in better // performance. However, in certain cases, the opposite is true.'' // // The standard workaround is to use -Dsun.java2d.pmoffscreen=false, // but this is too hard for some users, so provide an option to // do it easily. However respect the initial value if present. // // Remove this if Java 2D is ever fixed. DHYB. // final String pmoffscreen = "sun.java2d.pmoffscreen"; BooleanOption usePixmaps = (BooleanOption) opts.getOption(ClientOptions.USE_PIXMAPS); String pmoffscreenValue = System.getProperty(pmoffscreen); if (pmoffscreenValue == null) { System.setProperty(pmoffscreen, usePixmaps.getValue().toString()); logger.info(pmoffscreen + " using client option: " + usePixmaps.getValue().toString()); } else { usePixmaps.setValue(new Boolean(pmoffscreenValue)); logger.info(pmoffscreen + " overrides client option: " + pmoffscreenValue); } usePixmaps.addPropertyChangeListener(new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent e) { String newValue = e.getNewValue().toString(); System.setProperty(pmoffscreen, newValue); logger.info("Set " + pmoffscreen + " to: " + newValue); } }); this.mapViewer = new MapViewer(freeColClient, this, innerWindowSize, imageLibrary); this.canvas = new Canvas(freeColClient, this, innerWindowSize, mapViewer); this.colonyTileGUI = new MapViewer(freeColClient, this, innerWindowSize, imageLibrary); changeWindowedMode(isWindowed()); frame.setIconImage(ResourceManager.getImage("FrameIcon.image")); // Now that there is a canvas, prepare for language changes. LanguageOption o = (LanguageOption) freeColClient.getClientOptions().getOption(ClientOptions.LANGUAGE); if (o != null) { o.addPropertyChangeListener(new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent e) { if (((Language) e.getNewValue()).getKey().equals(LanguageOption.AUTO)) { showInformationMessage("autodetectLanguageSelected"); } else { Locale l = ((Language) e.getNewValue()).getLocale(); Messages.setMessageBundle(l); showInformationMessage(StringTemplate.template("newLanguageSelected") .addName("%language%", l.getDisplayName())); } } }); } // run opening video or main panel if (showOpeningVideo && !loadGame) { SwingUtilities.invokeLater(new Runnable() { public void run() { canvas.showOpeningVideoPanel(); } }); } else { if (!loadGame) { showMainPanel(); } playSound("sound.intro.general"); } mapViewer.startCursorBlinking(); } public void startMapEditorGUI() { // We may need to reset the zoom value to the default value scaleMap(2f); setupMapEditorMenuBar(); canvas.showMapEditorTransformPanel(); setupMouseListenerForMapEditor(); } public void toggleViewMode() { mapViewer.toggleViewMode(); } /** * Try to remove a unit from a colony. * - Check for population limit. * - Query if education should be abandoned. * * @param unit The <code>Unit</code> that is leaving the colony. * @return True if the unit is allowed to leave. */ public boolean tryLeaveColony(Unit unit) { Colony colony = unit.getColony(); String message = colony.getReducePopulationMessage(); if (message != null) { showInformationMessage(message); return false; } return confirmAbandonEducation(unit, true); } /** * Confirms that a unit should move somewhere where it would have * to abandon its participation in education (if any). * * @param unit The <code>Unit</code> to check. * @param checkStudent Should we check for student movements. * @return True if the unit should proceed to move. */ public boolean confirmAbandonEducation(Unit unit, boolean checkStudent) { StringTemplate message = unit.getAbandonEducationMessage(checkStudent); return message == null || showConfirmDialog(unit.getTile(), message, "abandonEducation.yes", "abandonEducation.no"); } public void updateGameOptions() { canvas.updateGameOptions(); } public void updateMapGeneratorOptions() { canvas.updateMapGeneratorOptions(); } public void updateMenuBar() { if (frame != null && frame.getJMenuBar() != null) { ((FreeColMenuBar) frame.getJMenuBar()).update(); } } private void setupMapEditorMenuBar() { frame.setJMenuBar(new MapEditorMenuBar(freeColClient, this)); } private void setupMouseListenerForMapEditor() { CanvasMapEditorMouseListener listener = new CanvasMapEditorMouseListener(freeColClient, this, canvas); canvas.addMouseListener(listener); canvas.addMouseMotionListener(listener); } public Parameters showParametersDialog() { return canvas.showParametersDialog(); } public Dimension showScaleMapSizeDialog() { return canvas.showScaleMapSizeDialog(); } public void showMapControls(boolean value) { if (value && freeColClient.isInGame()) { if (mapControls == null) { try { String className = freeColClient.getClientOptions() .getString(ClientOptions.MAP_CONTROLS); Class<?> controls = Class.forName("net.sf.freecol.client.gui.panel." + className); mapControls = (MapControls) controls.getConstructor(FreeColClient.class, GUI.class) .newInstance(freeColClient, this); } catch(Exception e) { mapControls = new CornerMapControls(freeColClient, this); } } mapControls.update(); } if (mapControls != null) { if (value) { if (!mapControls.isShowing()) { mapControls.addToComponent(canvas); } mapControls.update(); } else { if (mapControls.isShowing()) { mapControls.removeFromComponent(canvas); } } } } public void updateMapControls() { if (mapControls != null) mapControls.update(); } public void updateMapControlsInCanvas() { if (mapControls != null && mapControls.isShowing()) { mapControls.removeFromComponent(canvas); mapControls.addToComponent(canvas); } } public void zoomInMapControls() { mapControls.zoomIn(); } public void zoomOutMapControls() { mapControls.zoomOut(); } public boolean canZoomInMapControls() { return mapControls != null && mapControls.canZoomInMapControls(); } public boolean canZoomOutMapControls() { return mapControls != null && mapControls.canZoomOutMapControls(); } /** * Common utility routine to retrieve animation speed. * * @param unit The <code>Unit</code> to be animated. * @return The animation speed. */ public int getAnimationSpeed(Unit unit) { String key = (freeColClient.getMyPlayer() == unit.getOwner()) ? ClientOptions.MOVE_ANIMATION_SPEED : ClientOptions.ENEMY_MOVE_ANIMATION_SPEED; return freeColClient.getClientOptions().getInteger(key); } public void animateUnitAttack(Unit unit, Unit defender, boolean success) { Animations.unitAttack(this, unit, defender, success); } public void animateUnitMove(Unit unit, Tile sourceTile, Tile destinationTile) { Animations.unitMove(this, unit, sourceTile, destinationTile); } public BufferedImage createMiniMapThumbNail() { MiniMap miniMap = new MiniMap(freeColClient, this); miniMap.setTileSize(MiniMap.MAX_TILE_SIZE); int width = freeColClient.getGame().getMap().getWidth() * MiniMap.MAX_TILE_SIZE + MiniMap.MAX_TILE_SIZE/2; int height = freeColClient.getGame().getMap().getHeight() * MiniMap.MAX_TILE_SIZE / 4; BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); Graphics2D g2d = image.createGraphics(); miniMap.paintMap(g2d); // TODO: this can probably done more efficiently // by applying a suitable AffineTransform to the // Graphics2D double scaledWidth = Math.min((64 * width) / height, 128); BufferedImage scaledImage = new BufferedImage((int) scaledWidth, 64, BufferedImage.TYPE_INT_ARGB); scaledImage.createGraphics().drawImage(image, 0, 0, (int) scaledWidth, 64, null); return scaledImage; } }