Various fixes to the map editor and action logic.

* Store panel positions and sizes (if enabled) in more cases (for example, before closing all panels when starting a new game or creating a new map).
* Don't store sizes and positions for fullscreen panels.
* Adds title to map editor frames.
* Plays the default music playlist in the editor.
* Add an action/menu item for disabling/enabling the tile transform panel in the meap editor.
This commit is contained in:
Stian Grenborgen 2024-01-06 19:03:16 +01:00
parent 394d591169
commit 036dd1edfa
19 changed files with 291 additions and 68 deletions

View File

@ -392,6 +392,7 @@ loadAction.accelerator=L
loadAction.name=Load
mapControlsAction.accelerator=control M
mapControlsAction.name=Map Controls
mapEditorTransformPanelAction.name=Tile Transform
mapEditorAction.name=Map Editor
mapGeneratorOptionsAction.accelerator=shift F12
mapGeneratorOptionsAction.name=Show Map Generator Options
@ -3612,7 +3613,7 @@ loadingSavegameDialog.name=Loading Save game
mapEditor.loadedWithMods=You have started the map editor with active mods that contain specification changes. Please note that the same mods need to be manually activated by every user that loads maps that are using anything new from a mod.\n\nYou can go back to the main menu and deactivate any mods through the Preferences if this was not intentional.
# MapEditorTransformPanel
mapEditorTransformPanel.title=Paint
mapEditorTransformPanel.title=Tile Transform
mapEditorTransformPanel.chooseResource=Choose resource
mapEditorTransformPanel.majorRiver=Major river
mapEditorTransformPanel.minorRiver=Minor river

View File

@ -32,6 +32,7 @@ import javax.swing.SwingUtilities;
import javax.xml.stream.XMLStreamException;
import net.sf.freecol.FreeCol;
import net.sf.freecol.client.ClientOptions;
import net.sf.freecol.client.FreeColClient;
import net.sf.freecol.client.gui.GUI;
import net.sf.freecol.client.gui.panel.MiniMap; // FIXME: should go away
@ -48,6 +49,8 @@ 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.option.MapGeneratorOptions;
import net.sf.freecol.common.resources.AudioResource;
import net.sf.freecol.common.resources.ResourceManager;
import net.sf.freecol.server.FreeColServer;
import net.sf.freecol.server.generator.MapGenerator;
import net.sf.freecol.server.model.ServerGame;
@ -164,6 +167,11 @@ public final class MapEditorController extends FreeColClientHolder {
//fcc.changeClientState(true);
//gui.changeView((Tile)null);
gui.startMapEditorGUI();
final AudioResource defaultPlaylist = ResourceManager.getAudioResource("sound.music.playlist.default", true);
if (defaultPlaylist != null) {
getFreeColClient().getSoundController().setDefaultPlaylist(defaultPlaylist.getAllAudio());
}
getFreeColClient().getSoundController().playMusic(null);
if (specificationChanges) {
gui.showInformationPanel("mapEditor.loadedWithMods");
@ -327,6 +335,8 @@ public final class MapEditorController extends FreeColClientHolder {
SwingUtilities.invokeLater(() -> {
gui.closeStatusPanel();
gui.setFocus(game.getMap().getTile(1,1));
gui.enableEditorTransformPanel(true);
gui.enableMapControls(getClientOptions().getBoolean(ClientOptions.DISPLAY_MAP_CONTROLS));
gui.updateMenuBar();
gui.refresh();
});

View File

@ -1167,6 +1167,13 @@ public final class Canvas extends JDesktopPane {
* requested type, or null if none found.
*/
public <T extends FreeColPanel> T getExistingFreeColPanel(Class<T> type) {
for (JInternalFrame f : getAllFrames()) {
for (Component c2 : f.getContentPane().getComponents()) {
if (type.isAssignableFrom(c2.getClass())) {
return type.cast(c2);
}
}
}
for (Component c1 : getComponents()) {
if (c1 instanceof JInternalFrame) {
for (Component c2 : ((JInternalFrame)c1).getContentPane()
@ -1188,6 +1195,22 @@ public final class Canvas extends JDesktopPane {
return null;
}
public boolean isAddedAsPanelFrameOrIcon(Class<?> clazz) {
for (JInternalFrame f : getAllFrames()) {
for (Component c2 : f.getContentPane().getComponents()) {
if (clazz.isAssignableFrom(c2.getClass())) {
return true;
}
}
}
for (Component c1 : getComponents()) {
if (clazz.isAssignableFrom(c1.getClass())) {
return true;
}
}
return false;
}
public boolean isAddedAsPanelFrameOrIcon(Component component) {
for (JInternalFrame f : getAllFrames()) {
for (Component c2 : f.getContentPane().getComponents()) {

View File

@ -1158,6 +1158,18 @@ public class GUI extends FreeColClientHolder {
*/
public void startMapEditorGUI() {}
/**
* Shows the map editor transform panel.
*/
public void enableEditorTransformPanel(boolean shouldDisplayPanel) {}
/**
* Checks if the map editor transform panel is being displayed.
*/
public boolean isShowingMapEditorTransformPanel() {
return false;
}
// Animation handling

View File

@ -60,6 +60,7 @@ import net.sf.freecol.client.ClientOptions;
import net.sf.freecol.client.FreeColClient;
import net.sf.freecol.client.control.MapTransform;
import net.sf.freecol.client.control.SoundController;
import net.sf.freecol.client.gui.action.MapEditorTransformPanelAction;
import net.sf.freecol.client.gui.animation.Animation;
import net.sf.freecol.client.gui.animation.Animations;
// Special dialogs and panels
@ -71,12 +72,14 @@ import net.sf.freecol.client.gui.mapviewer.MapAsyncPainter;
import net.sf.freecol.client.gui.mapviewer.MapViewer;
import net.sf.freecol.client.gui.mapviewer.MapViewerState;
import net.sf.freecol.client.gui.mapviewer.TileViewer;
import net.sf.freecol.client.gui.panel.BuildQueuePanel;
import net.sf.freecol.client.gui.panel.ColonyPanel;
import net.sf.freecol.client.gui.panel.CornerMapControls;
import net.sf.freecol.client.gui.panel.FreeColImageBorder;
import net.sf.freecol.client.gui.panel.FreeColPanel;
import net.sf.freecol.client.gui.panel.InformationPanel;
import net.sf.freecol.client.gui.panel.MapControls;
import net.sf.freecol.client.gui.panel.MapEditorTransformPanel;
import net.sf.freecol.client.gui.panel.PurchasePanel;
import net.sf.freecol.client.gui.panel.RecruitPanel;
import net.sf.freecol.client.gui.panel.StartGamePanel;
@ -123,6 +126,7 @@ 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.resources.AudioResource;
import net.sf.freecol.common.resources.ImageCache;
import net.sf.freecol.common.resources.ImageResource;
import net.sf.freecol.common.resources.ResourceManager;
@ -831,7 +835,7 @@ public class SwingGUI extends GUI {
this.mapViewer.getMapViewerBounds().setFocus(tile);
enableMapControls(false);
enableMapControls(getClientOptions().getBoolean(ClientOptions.DISPLAY_MAP_CONTROLS));
enableMapControls(getGame() != null && getGame().getMap() != null && getClientOptions().getBoolean(ClientOptions.DISPLAY_MAP_CONTROLS));
refresh();
}
@ -916,7 +920,30 @@ public class SwingGUI extends GUI {
resetMapZoom(); // Reset zoom to the default
mapViewer.getMapViewerState().setActiveUnit(null);
this.canvas.startMapEditorGUI();
this.canvas.showMapEditorTransformPanel();
enableEditorTransformPanel(getGame() != null && getGame().getMap() != null);
enableMapControls(getGame() != null && getGame().getMap() != null && getClientOptions().getBoolean(ClientOptions.DISPLAY_MAP_CONTROLS));
updateMenuBar();
}
/**
* {@inheritDoc}
*/
@Override
public void enableEditorTransformPanel(boolean shouldDisplayPanel) {
final MapEditorTransformPanel panel = this.canvas.getExistingFreeColPanel(MapEditorTransformPanel.class);
if (shouldDisplayPanel && panel == null) {
this.canvas.showMapEditorTransformPanel();
} else if (!shouldDisplayPanel && panel != null) {
this.canvas.removeFromCanvas(panel);
} // else: ignore.
}
/**
* {@inheritDoc}
*/
@Override
public boolean isShowingMapEditorTransformPanel() {
return this.canvas.isAddedAsPanelFrameOrIcon(MapEditorTransformPanel.class);
}

View File

@ -119,6 +119,7 @@ public class ActionManager extends OptionGroup {
add(new LoadAction(freeColClient));
add(new MapControlsAction(freeColClient));
add(new MapEditorAction(freeColClient));
add(new MapEditorTransformPanelAction(freeColClient));
add(new MiniMapToggleViewAction(freeColClient));
add(new MiniMapToggleViewAction(freeColClient, true));
add(new MiniMapToggleFogOfWarAction(freeColClient));

View File

@ -28,7 +28,7 @@ import net.sf.freecol.client.gui.GUI;
/**
* An action for toggling between full-screen and windowed mode.
*/
public final class ChangeWindowedModeAction extends SelectableAction {
public final class ChangeWindowedModeAction extends SelectableOptionAction {
public static final String id = "changeWindowedModeAction";

View File

@ -30,7 +30,7 @@ import net.sf.freecol.client.FreeColClient;
/**
* An action to toggle the display of national borders.
*/
public class DisplayBordersAction extends SelectableAction {
public class DisplayBordersAction extends SelectableOptionAction {
public static final String id = "displayBordersAction";

View File

@ -31,7 +31,7 @@ import net.sf.freecol.common.option.GameOptions;
/**
* An action to toggle the display of national borders.
*/
public class DisplayFogOfWarAction extends SelectableAction {
public class DisplayFogOfWarAction extends SelectableOptionAction {
public static final String id = "displayFogOfWarAction";

View File

@ -30,7 +30,7 @@ import net.sf.freecol.client.FreeColClient;
/**
* An action to toggle the display of the map grid.
*/
public class DisplayGridAction extends SelectableAction {
public class DisplayGridAction extends SelectableOptionAction {
public static final String id = "displayGridAction";

View File

@ -34,7 +34,7 @@ import static net.sf.freecol.common.util.StringUtils.*;
/**
* Display text over tiles.
*/
public final class DisplayTileTextAction extends SelectableAction {
public final class DisplayTileTextAction extends SelectableOptionAction {
public static final String id = "displayTileTextAction.";

View File

@ -21,8 +21,6 @@ package net.sf.freecol.client.gui.action;
import java.awt.event.ActionEvent;
import javax.swing.AbstractButton;
import net.sf.freecol.client.ClientOptions;
import net.sf.freecol.client.FreeColClient;
@ -30,7 +28,7 @@ import net.sf.freecol.client.FreeColClient;
/**
* An action for displaying the map controls.
*/
public class MapControlsAction extends SelectableAction {
public class MapControlsAction extends SelectableOptionAction {
public static final String id = "mapControlsAction";
@ -55,10 +53,20 @@ public class MapControlsAction extends SelectableAction {
@Override
public void update() {
super.update();
getGUI().enableMapControls(isEnabled() && isSelected());
}
/**
* {@inheritDoc}
*/
@Override
protected boolean shouldBeEnabled() {
return super.shouldBeEnabled() && getGame() != null && getGame().getMap() != null;
}
@Override
protected boolean shouldBeSelected() {
return getOption();
}
// Interface ActionListener
@ -67,8 +75,7 @@ public class MapControlsAction extends SelectableAction {
*/
@Override
public void actionPerformed(ActionEvent ae) {
setSelected(((AbstractButton)ae.getSource()).isSelected());
getGUI().enableMapControls(isEnabled() && isSelected());
setOption(isSelected());
update();
}
}

View File

@ -0,0 +1,68 @@
/**
* Copyright (C) 2002-2022 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.action;
import java.awt.event.ActionEvent;
import javax.swing.AbstractButton;
import net.sf.freecol.client.ClientOptions;
import net.sf.freecol.client.FreeColClient;
/**
* An action for displaying the map controls.
*/
public class MapEditorTransformPanelAction extends SelectableAction {
public static final String id = "mapEditorTransformPanelAction";
/**
* Creates this action.
*
* @param freeColClient The {@code FreeColClient} for the game.
*/
public MapEditorTransformPanelAction(FreeColClient freeColClient) {
super(freeColClient, id);
setSelected(isSelected());
}
@Override
protected boolean shouldBeEnabled() {
return freeColClient.isMapEditor() && getGame() != null && getGame().getMap() != null;
}
@Override
protected boolean shouldBeSelected() {
return getGUI().isShowingMapEditorTransformPanel();
}
// Interface ActionListener
/**
* {@inheritDoc}
*/
@Override
public void actionPerformed(ActionEvent ae) {
getGUI().enableEditorTransformPanel(isEnabled() && isSelected());
}
}

View File

@ -22,7 +22,9 @@ package net.sf.freecol.client.gui.action;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import net.sf.freecol.client.ClientOptions;
import net.sf.freecol.client.FreeColClient;
import net.sf.freecol.client.gui.GUI;
import net.sf.freecol.common.model.Map;
import net.sf.freecol.common.model.Tile;
@ -68,6 +70,8 @@ public class NewEmptyMapAction extends MapboardAction {
Map map = getFreeColClient().getFreeColServer()
.generateEmptyMap(size.width, size.height);
Tile tile = map.getTile(size.width/2, size.height/2);
getGUI().enableEditorTransformPanel(true);
getGUI().enableMapControls(getClientOptions().getBoolean(ClientOptions.DISPLAY_MAP_CONTROLS));
getGUI().setFocus(tile);
getGUI().updateMenuBar();
getGUI().refresh();

View File

@ -19,64 +19,27 @@
package net.sf.freecol.client.gui.action;
import java.util.logging.Level;
import javax.swing.Action;
import net.sf.freecol.client.FreeColClient;
import net.sf.freecol.client.ClientOptions;
/**
* An action for selecting one of several options.
* An action for a boolean value.
*/
public abstract class SelectableAction extends MapboardAction {
public static final String id = "selectableAction";
private final String optionId;
protected boolean selected = false;
/**
* Creates this action.
*
* @param freeColClient The {@code FreeColClient} for the game.
* @param id The object identifier.
* @param optionId The identifier of a boolean client option.
*/
protected SelectableAction(FreeColClient freeColClient,
String id, String optionId) {
protected SelectableAction(FreeColClient freeColClient, String id) {
super(freeColClient, id);
this.optionId = optionId;
}
/**
* Get the value of the underlying option.
*
* @return The option value.
*/
public final boolean getOption() {
ClientOptions co = freeColClient.getClientOptions();
if (co != null && optionId != null) {
try {
return co.getBoolean(optionId);
} catch (Exception e) {
logger.log(Level.WARNING, "Failure with option: " + optionId, e);
}
}
return false;
}
/**
* Set the option value.
*
* @param value The new boolean value.
*/
public final void setOption(boolean value) {
ClientOptions co = freeColClient.getClientOptions();
if (co != null && optionId != null) co.setBoolean(optionId, value);
}
/**
@ -85,7 +48,7 @@ public abstract class SelectableAction extends MapboardAction {
* @return True if this action is selected.
*/
public final boolean isSelected() {
return selected;
return Boolean.TRUE.equals(getValue(Action.SELECTED_KEY));
}
/**
@ -94,7 +57,7 @@ public abstract class SelectableAction extends MapboardAction {
* @param b The new selection value.
*/
public final void setSelected(boolean b) {
this.selected = b;
putValue(Action.SELECTED_KEY, b);
}
/**
@ -105,7 +68,7 @@ public abstract class SelectableAction extends MapboardAction {
* @return True of this action should be selected.
*/
protected boolean shouldBeSelected() {
return getOption();
return isSelected();
}

View File

@ -0,0 +1,92 @@
/**
* Copyright (C) 2002-2022 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.action;
import java.util.logging.Level;
import net.sf.freecol.client.FreeColClient;
import net.sf.freecol.client.ClientOptions;
/**
* An action for selecting one of several options.
*/
public abstract class SelectableOptionAction extends SelectableAction {
public static final String id = "selectableOptionAction";
private final String optionId;
protected boolean selected = false;
/**
* Creates this action.
*
* @param freeColClient The {@code FreeColClient} for the game.
* @param id The object identifier.
* @param optionId The identifier of a boolean client option.
*/
protected SelectableOptionAction(FreeColClient freeColClient,
String id, String optionId) {
super(freeColClient, id);
this.optionId = optionId;
}
/**
* Get the value of the underlying option.
*
* @return The option value.
*/
public final boolean getOption() {
ClientOptions co = freeColClient.getClientOptions();
if (co != null && optionId != null) {
try {
return co.getBoolean(optionId);
} catch (Exception e) {
logger.log(Level.WARNING, "Failure with option: " + optionId, e);
}
}
return false;
}
/**
* Set the option value.
*
* @param value The new boolean value.
*/
public final void setOption(boolean value) {
ClientOptions co = freeColClient.getClientOptions();
if (co != null && optionId != null) co.setBoolean(optionId, value);
}
/**
* Should this action be selected?
*
* Override this in subclasses.
*
* @return True of this action should be selected.
*/
protected boolean shouldBeSelected() {
return getOption();
}
}

View File

@ -19,7 +19,6 @@
package net.sf.freecol.client.gui.menu;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
@ -41,6 +40,7 @@ import net.sf.freecol.client.gui.action.ColopediaAction;
import net.sf.freecol.client.gui.action.ColopediaAction.PanelType;
import net.sf.freecol.client.gui.action.FreeColAction;
import net.sf.freecol.client.gui.action.SelectableAction;
import net.sf.freecol.client.gui.action.SelectableOptionAction;
import net.sf.freecol.client.gui.panel.FreeColImageBorder;
import net.sf.freecol.client.gui.panel.Utility;
import net.sf.freecol.common.util.ImageUtils;
@ -166,7 +166,6 @@ public abstract class FreeColMenuBar extends JMenuBar {
* @return The menu item.
*/
protected JCheckBoxMenuItem getCheckBoxMenuItem(String actionId) {
JCheckBoxMenuItem rtn = null;
FreeColAction action = am.getFreeColAction(actionId);
@ -175,11 +174,10 @@ public abstract class FreeColMenuBar extends JMenuBar {
rtn.setAction(action);
rtn.setOpaque(false);
rtn.setSelected(((SelectableAction)am.getFreeColAction(actionId))
.isSelected());
} else
logger.finest("Could not create menu item. [" + actionId
+ "] not found.");
//rtn.setSelected(((SelectableAction) am.getFreeColAction(actionId)).isSelected());
} else {
logger.finest("Could not create menu item. [" + actionId + "] not found.");
}
return rtn;
}
@ -202,7 +200,7 @@ public abstract class FreeColMenuBar extends JMenuBar {
rtn.setAction(action);
rtn.setOpaque(false);
rtn.setSelected(((SelectableAction) am.getFreeColAction(actionId)).isSelected());
rtn.setSelected(((SelectableOptionAction) am.getFreeColAction(actionId)).isSelected());
group.add(rtn);
} else {
logger.finest("Could not create menu item. [" + actionId

View File

@ -33,6 +33,7 @@ import net.sf.freecol.client.gui.action.DisplayGridAction;
import net.sf.freecol.client.gui.action.DisplayTileTextAction;
import net.sf.freecol.client.gui.action.DisplayTileTextAction.DisplayText;
import net.sf.freecol.client.gui.action.MapControlsAction;
import net.sf.freecol.client.gui.action.MapEditorTransformPanelAction;
import net.sf.freecol.client.gui.action.NewAction;
import net.sf.freecol.client.gui.action.NewEmptyMapAction;
import net.sf.freecol.client.gui.action.OpenAction;
@ -130,6 +131,7 @@ public class MapEditorMenuBar extends FreeColMenuBar {
menu.setMnemonic(KeyEvent.VK_V);
menu.add(getCheckBoxMenuItem(MapControlsAction.id));
menu.add(getCheckBoxMenuItem(MapEditorTransformPanelAction.id));
menu.add(getCheckBoxMenuItem(DisplayGridAction.id));
menu.add(getCheckBoxMenuItem(ChangeWindowedModeAction.id));

View File

@ -32,8 +32,10 @@ import java.util.logging.Logger;
import java.util.stream.Collectors;
import javax.swing.JComponent;
import javax.swing.JInternalFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import net.miginfocom.swing.MigLayout;
import net.sf.freecol.client.ClientOptions;
@ -301,8 +303,13 @@ public final class CornerMapControls extends MapControls {
@Override
public List<JComponent> getComponentsPresent() {
List<JComponent> ret = new ArrayList<>();
ret.add(this.infoPanel);
ret.add(this.miniMapPanel);
if (isShowingOrIconified(this.infoPanel)) {
ret.add(this.infoPanel);
}
if (isShowingOrIconified(this.miniMapPanel)) {
ret.add(this.miniMapPanel);
}
final boolean rose = getClientOptions()
.getBoolean(ClientOptions.DISPLAY_COMPASS_ROSE);
if (rose && this.compassRose.isShowing()) ret.add(this.compassRose);
@ -311,4 +318,12 @@ public final class CornerMapControls extends MapControls {
}
return ret;
}
private boolean isShowingOrIconified(JComponent panel) {
final JInternalFrame f = (JInternalFrame) SwingUtilities.getAncestorOfClass(JInternalFrame.class, panel);
if (f != null && f.isIcon()) {
return true;
}
return panel.isShowing();
}
}