GUI, game: improved battlefield sizing (part of #6887 and #969):

- fixed wrong restore of card hint and chat panels;
- now it keep hidden state too (e.g. hidden card hint);
- reworked and share splitters code;
- removed some useless hotkeys to show/hide card hint panel;
This commit is contained in:
Oleg Agafonov 2024-08-13 23:49:39 +04:00
parent 3285f48aba
commit 58400833bc
8 changed files with 168 additions and 214 deletions

View file

@ -758,10 +758,11 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
public static void deactivate(MagePane frame) { public static void deactivate(MagePane frame) {
frame.setVisible(false); frame.setVisible(false);
setActive(getTopMost(frame)); MagePane topPane = getTopMost(frame);
if (activeFrame != frame) { if (topPane == frame) {
frame.deactivated(); throw new IllegalArgumentException("Impossible use case - deactivated frame can't ref to itself");
} }
setActive(topPane);
} }
public static MagePane getTopMost(MagePane exclude) { public static MagePane getTopMost(MagePane exclude) {

View file

@ -106,8 +106,6 @@ public class PreferencesDialog extends javax.swing.JDialog {
public static final String SOUNDS_MATCH_MUSIC_ENABLE_BY_DEFAULT = "true"; public static final String SOUNDS_MATCH_MUSIC_ENABLE_BY_DEFAULT = "true";
public static final String KEY_SOUNDS_MATCH_MUSIC_PATH = "soundsMatchMusicPath"; public static final String KEY_SOUNDS_MATCH_MUSIC_PATH = "soundsMatchMusicPath";
public static final String KEY_BIG_CARD_TOGGLED = "bigCardToggled";
// Themes // Themes
public static final String KEY_THEME = "themeSelection"; public static final String KEY_THEME = "themeSelection";
@ -183,7 +181,10 @@ public class PreferencesDialog extends javax.swing.JDialog {
public static final String KEY_GAMEPANEL_DIVIDER_LOCATION_0 = "gamepanelDividerLocation0"; public static final String KEY_GAMEPANEL_DIVIDER_LOCATION_0 = "gamepanelDividerLocation0";
public static final String KEY_GAMEPANEL_DIVIDER_LOCATION_1 = "gamepanelDividerLocation1"; public static final String KEY_GAMEPANEL_DIVIDER_LOCATION_1 = "gamepanelDividerLocation1";
public static final String KEY_GAMEPANEL_DIVIDER_LOCATIONS_GAME_AND_BIG_CARD = "gamepanelDividerLocationsGameAndBigCard";
public static final String KEY_GAMEPANEL_DIVIDER_LOCATIONS_BATTLEFIELD_AND_CHATS = "gamepanelDividerLocationsBattlefieldAndChats";
public static final String KEY_GAMEPANEL_DIVIDER_LOCATIONS_HAND_STACK = "gamepanelDividerLocationsHandStack"; public static final String KEY_GAMEPANEL_DIVIDER_LOCATIONS_HAND_STACK = "gamepanelDividerLocationsHandStack";
public static final String KEY_GAMEPANEL_DIVIDER_LOCATIONS_CHAT_AND_LOGS = "gamepanelDividerLocationsChatAndLogs";
public static final String KEY_GAMEPANEL_DIVIDER_LOCATION_2 = "gamepanelDividerLocation2"; public static final String KEY_GAMEPANEL_DIVIDER_LOCATION_2 = "gamepanelDividerLocation2";
public static final String KEY_TOURNAMENT_PLAYER_COLUMNS_WIDTH = "tournamentPlayerPanelColumnWidth"; public static final String KEY_TOURNAMENT_PLAYER_COLUMNS_WIDTH = "tournamentPlayerPanelColumnWidth";

View file

@ -67,13 +67,6 @@ public class GamePane extends MagePane {
gamePanel.replayGame(gameId); gamePanel.replayGame(gameId);
} }
/**
* Called on game frame prepared and showed as top panel (on new game started, on panel switch from main menu, etc)
*/
public void onShow() {
gamePanel.restoreDividerLocations();
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private void initComponents() { private void initComponents() {
@ -104,6 +97,7 @@ public class GamePane extends MagePane {
@Override @Override
public void deactivated() { public void deactivated() {
super.deactivated();
gamePanel.onDeactivated(); gamePanel.onDeactivated();
} }

View file

@ -113,7 +113,6 @@ public final class GamePanel extends javax.swing.JPanel {
private final PickMultiNumberDialog pickMultiNumber; private final PickMultiNumberDialog pickMultiNumber;
private JLayeredPane jLayeredPane; private JLayeredPane jLayeredPane;
private String chosenHandKey = "You"; private String chosenHandKey = "You";
private boolean initialized = false;
private final skipButtonsList skipButtons = new skipButtonsList(); private final skipButtonsList skipButtons = new skipButtonsList();
private boolean menuNameSet = false; private boolean menuNameSet = false;
@ -124,6 +123,22 @@ public final class GamePanel extends javax.swing.JPanel {
private int storedHeight; private int storedHeight;
private final Map<String, HoverButton> phaseButtons = new LinkedHashMap<>(); // phase name, phase button private final Map<String, HoverButton> phaseButtons = new LinkedHashMap<>(); // phase name, phase button
// splitters with save and restore feature
// TODO: use same logic for draft and deck editor splitters like SplitterManager
private final Map<String, MageSplitter> splitters = new LinkedHashMap<>(); // settings key, splitter
// do not save splitters in intermediate state, e.g. connection to new server with active game
private boolean isSplittersFullyRestored = false;
public static class MageSplitter {
JSplitPane splitPane;
double defaultProportion;
MageSplitter(JSplitPane splitPane, double defaultProportion) {
this.splitPane = splitPane;
this.defaultProportion = defaultProportion;
}
}
private MageDialogState choiceWindowState; private MageDialogState choiceWindowState;
private boolean initComponents; private boolean initComponents;
@ -232,13 +247,13 @@ public final class GamePanel extends javax.swing.JPanel {
pnlCommandsSkipAndStack.add(pnlShortCuts, BorderLayout.NORTH); pnlCommandsSkipAndStack.add(pnlShortCuts, BorderLayout.NORTH);
pnlCommandsSkipAndStack.add(stackObjects, BorderLayout.CENTER); pnlCommandsSkipAndStack.add(stackObjects, BorderLayout.CENTER);
// ... split: feedback + hand <|> skip + stack // ... split: feedback + hand <|> skip + stack
jSplitPaneHandStack.setLeftComponent(pnlCommandsFeedbackAndHand); splitHandAndStack.setLeftComponent(pnlCommandsFeedbackAndHand);
jSplitPaneHandStack.setRightComponent(pnlCommandsSkipAndStack); splitHandAndStack.setRightComponent(pnlCommandsSkipAndStack);
jSplitPaneHandStack.setResizeWeight(DIVIDER_KEEP_RIGHT_COMPONENT); splitHandAndStack.setResizeWeight(DIVIDER_KEEP_RIGHT_COMPONENT);
pnlCommandsFeedbackAndHand.setMinimumSize(new Dimension(0, 0)); // allow any sizes for hand pnlCommandsFeedbackAndHand.setMinimumSize(new Dimension(0, 0)); // allow any sizes for hand
pnlCommandsSkipAndStack.setMinimumSize(new Dimension(0, 0)); // allow any sizes for stack pnlCommandsSkipAndStack.setMinimumSize(new Dimension(0, 0)); // allow any sizes for stack
// ... all // ... all
pnlCommandsRoot.add(jSplitPaneHandStack, BorderLayout.CENTER); pnlCommandsRoot.add(splitHandAndStack, BorderLayout.CENTER);
pnlHelperHandButtonsStackArea.add(pnlCommandsRoot, BorderLayout.SOUTH); pnlHelperHandButtonsStackArea.add(pnlCommandsRoot, BorderLayout.SOUTH);
// prepare commands buttons panel with flow layout (instead custom from IDE) // prepare commands buttons panel with flow layout (instead custom from IDE)
@ -275,7 +290,7 @@ public final class GamePanel extends javax.swing.JPanel {
final JLayeredPane jLayeredBackgroundPane = new JLayeredPane(); final JLayeredPane jLayeredBackgroundPane = new JLayeredPane();
jLayeredBackgroundPane.setSize(1024, 768); jLayeredBackgroundPane.setSize(1024, 768);
this.add(jLayeredBackgroundPane); this.add(jLayeredBackgroundPane);
jLayeredBackgroundPane.add(jSplitPane0, JLayeredPane.DEFAULT_LAYER); jLayeredBackgroundPane.add(splitGameAndBigCard, JLayeredPane.DEFAULT_LAYER);
Map<String, JComponent> myUi = getUIComponents(jLayeredBackgroundPane); Map<String, JComponent> myUi = getUIComponents(jLayeredBackgroundPane);
Plugins.instance.updateGamePanel(myUi); Plugins.instance.updateGamePanel(myUi);
@ -287,23 +302,23 @@ public final class GamePanel extends javax.swing.JPanel {
int width = ((JComponent) e.getSource()).getWidth(); int width = ((JComponent) e.getSource()).getWidth();
int height = ((JComponent) e.getSource()).getHeight(); int height = ((JComponent) e.getSource()).getHeight();
jLayeredBackgroundPane.setSize(width, height); jLayeredBackgroundPane.setSize(width, height);
jSplitPane0.setSize(width, height); splitGameAndBigCard.setSize(width, height);
if (height < storedHeight) { if (height < storedHeight) {
// TODO: wtf, is it needs? Research and delete that code with storedHeight
pnlBattlefield.setSize(0, 200); pnlBattlefield.setSize(0, 200);
} }
storedHeight = height; storedHeight = height;
sizeToScreen(); sizeToScreen();
}
});
if (!initialized) { bigCardPanel.addComponentListener(new ComponentAdapter() {
String state = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_BIG_CARD_TOGGLED, null); @Override
if (state != null && state.equals("down")) { public void componentResized(ComponentEvent e) {
jSplitPane0.setDividerLocation(1.0); // TODO: on panel resize card don't want to redraw until new mouse move over card
} sizeBigCard();
initialized = true;
}
} }
}); });
@ -341,8 +356,10 @@ public final class GamePanel extends javax.swing.JPanel {
private Map<String, JComponent> getUIComponents(JLayeredPane jLayeredPane) { private Map<String, JComponent> getUIComponents(JLayeredPane jLayeredPane) {
Map<String, JComponent> components = new HashMap<>(); Map<String, JComponent> components = new HashMap<>();
components.put("jSplitPane1", jSplitPane1); components.put("splitChatAndLogs", splitChatAndLogs);
components.put("jSplitPaneHandStack", jSplitPaneHandStack); components.put("splitHandAndStack", splitHandAndStack);
components.put("splitBattlefieldAndChats", splitBattlefieldAndChats);
components.put("splitGameAndBigCard", splitGameAndBigCard);
components.put("pnlBattlefield", pnlBattlefield); components.put("pnlBattlefield", pnlBattlefield);
components.put("pnlHelperHandButtonsStackArea", pnlHelperHandButtonsStackArea); components.put("pnlHelperHandButtonsStackArea", pnlHelperHandButtonsStackArea);
components.put("hand", handContainer); components.put("hand", handContainer);
@ -357,12 +374,6 @@ public final class GamePanel extends javax.swing.JPanel {
public void cleanUp() { public void cleanUp() {
MageFrame.removeGame(gameId); MageFrame.removeGame(gameId);
// TODO: on 2+ games it called AFTER new game started, so second game will get old divider settings
// must be another way to save changed settings
// (not on change location -- there are big picture hotkeys to hide/show - it uses divider)
// So current solution: remove hidden big pucture feature and add save on change
saveDividerLocations();
this.gameChatPanel.cleanUp(); this.gameChatPanel.cleanUp();
this.userChatPanel.cleanUp(); this.userChatPanel.cleanUp();
@ -422,8 +433,6 @@ public final class GamePanel extends javax.swing.JPanel {
} catch (InterruptedException ex) { } catch (InterruptedException ex) {
logger.fatal("popupContainer error:", ex); logger.fatal("popupContainer error:", ex);
} }
jPanel2.remove(bigCard);
this.bigCard = null;
} }
private void hidePickDialogs() { private void hidePickDialogs() {
@ -503,16 +512,14 @@ public final class GamePanel extends javax.swing.JPanel {
} }
private void setGUISize(boolean themeReload) { private void setGUISize(boolean themeReload) {
jSplitPane0.setDividerSize(GUISizeHelper.dividerBarSize); splitters.values().forEach(splitter -> {
jSplitPane1.setDividerSize(GUISizeHelper.dividerBarSize); splitter.splitPane.setDividerSize(GUISizeHelper.dividerBarSize);
jSplitPaneHandStack.setDividerSize(GUISizeHelper.dividerBarSize); });
jSplitPane2.setDividerSize(GUISizeHelper.dividerBarSize);
txtHoldPriority.setFont(new Font(GUISizeHelper.gameFeedbackPanelFont.getFontName(), Font.BOLD, GUISizeHelper.gameFeedbackPanelFont.getSize())); txtHoldPriority.setFont(new Font(GUISizeHelper.gameFeedbackPanelFont.getFontName(), Font.BOLD, GUISizeHelper.gameFeedbackPanelFont.getSize()));
GUISizeHelper.changePopupMenuFont(popupMenuTriggerOrder); GUISizeHelper.changePopupMenuFont(popupMenuTriggerOrder);
// commands panel // commands panel
// TODO: add scrolls and save sizes instead const
// hand <|> stack // hand <|> stack
int upperPanelsHeight = getSkipButtonsPanelDefaultHeight(); int upperPanelsHeight = getSkipButtonsPanelDefaultHeight();
feedbackPanel.setPreferredSize(new Dimension(Short.MAX_VALUE, upperPanelsHeight)); feedbackPanel.setPreferredSize(new Dimension(Short.MAX_VALUE, upperPanelsHeight));
@ -576,8 +583,10 @@ public final class GamePanel extends javax.swing.JPanel {
// make sure it will get two rows of buttons // make sure it will get two rows of buttons
float guiScale = GUISizeHelper.dialogGuiScale; float guiScale = GUISizeHelper.dialogGuiScale;
int vGap = GUISizeHelper.guiSizeScale(SKIP_BUTTONS_SPACE_V, guiScale); int vGap = GUISizeHelper.guiSizeScale(SKIP_BUTTONS_SPACE_V, guiScale);
int extraSpace = GUISizeHelper.guiSizeScale(30, guiScale); // extra space for messages in feedback //int extraSpace = GUISizeHelper.guiSizeScale(30, guiScale); // extra space for messages in feedback
return extraSpace + (4 * vGap) + (2 * GUISizeHelper.gameCommandButtonHeight); int extraSpace = 0; // no needs in extra space for 3+ lines
int lines = 3;
return extraSpace + ((lines * 2 - 1) * vGap) + (lines * GUISizeHelper.gameCommandButtonHeight);
} }
private void reloadThemeRelatedGraphic() { private void reloadThemeRelatedGraphic() {
@ -622,7 +631,7 @@ public final class GamePanel extends javax.swing.JPanel {
playPanel.getPlayerPanel().fullRefresh(GUISizeHelper.playerPanelGuiScale); playPanel.getPlayerPanel().fullRefresh(GUISizeHelper.playerPanelGuiScale);
playPanel.init(player, bigCard, gameId, player.getPriorityTimeLeftSecs()); playPanel.init(player, bigCard, gameId, player.getPriorityTimeLeftSecs());
playPanel.update(lastGameData.game, player, lastGameData.targets); playPanel.update(lastGameData.game, player, lastGameData.targets);
playPanel.getPlayerPanel().sizePlayerPanel(isSmallMode()); playPanel.getPlayerPanel().sizePlayerPanel(false);
} }
}); });
} }
@ -644,21 +653,7 @@ public final class GamePanel extends javax.swing.JPanel {
} }
} }
private void saveDividerLocations() { private Map<String, Integer> loadSplitterLocationsFromSettings(String settingsKey) {
saveCurrentDividerLocation(jSplitPaneHandStack, PreferencesDialog.KEY_GAMEPANEL_DIVIDER_LOCATIONS_HAND_STACK);
// TODO: migrate to new version
// save panel sizes and divider locations.
Rectangle rec = MageFrame.getDesktop().getBounds();
String sb = Double.toString(rec.getWidth()) + 'x' + rec.getHeight();
PreferencesDialog.saveValue(PreferencesDialog.KEY_MAGE_PANEL_LAST_SIZE, sb);
PreferencesDialog.saveValue(PreferencesDialog.KEY_GAMEPANEL_DIVIDER_LOCATION_0, Integer.toString(this.jSplitPane0.getDividerLocation()));
PreferencesDialog.saveValue(PreferencesDialog.KEY_GAMEPANEL_DIVIDER_LOCATION_1, Integer.toString(this.jSplitPane1.getDividerLocation()));
//PreferencesDialog.saveValue(PreferencesDialog.KEY_GAMEPANEL_DIVIDER_LOCATION_HAND_STACK, Integer.toString(this.jSplitPaneHandStack.getDividerLocation()));
PreferencesDialog.saveValue(PreferencesDialog.KEY_GAMEPANEL_DIVIDER_LOCATION_2, Integer.toString(this.jSplitPane2.getDividerLocation()));
}
private Map<String, Integer> loadAllDividerLocations(String settingsKey) {
Map<String, Integer> res; Map<String, Integer> res;
Type type = new TypeToken<Map<String, Integer>>() { Type type = new TypeToken<Map<String, Integer>>() {
}.getType(); }.getType();
@ -677,26 +672,38 @@ public final class GamePanel extends javax.swing.JPanel {
return res; return res;
} }
private void saveAllDividerLocations(Map<String, Integer> newValues, String settingsKey) { private void saveSplitterLocationsToSettings(Map<String, Integer> newValues, String settingsKey) {
PreferencesDialog.saveValue(settingsKey, new Gson().toJson(newValues)); PreferencesDialog.saveValue(settingsKey, new Gson().toJson(newValues));
} }
private void saveCurrentDividerLocation(JSplitPane splitPane, String settingsKey) { private void saveSplitters() {
Map<String, Integer> allLocations = loadAllDividerLocations(settingsKey); if (!isSplittersFullyRestored) {
logger.warn("splitters do not fully restored yet");
return;
}
splitters.forEach((settingsKey, splitter) -> {
saveSplitter(splitter.splitPane, settingsKey);
});
}
private void saveSplitter(JSplitPane splitPane, String settingsKey) {
Map<String, Integer> allLocations = loadSplitterLocationsFromSettings(settingsKey);
Rectangle screenRec = MageFrame.getDesktop().getBounds(); Rectangle screenRec = MageFrame.getDesktop().getBounds();
String screenKey = String.format("%d_x_%d", screenRec.width, screenRec.height); String screenKey = String.format("%d_x_%d", screenRec.width, screenRec.height);
// store location or hidden state (left/right) // store location information (position or hidden state)
// splits with hidden panels will give location < min/max divider
int newLocation = splitPane.getDividerLocation(); int newLocation = splitPane.getDividerLocation();
if (newLocation == splitPane.getMinimumDividerLocation()) { if (newLocation == 0 || newLocation < splitPane.getMinimumDividerLocation()) {
newLocation = DIVIDER_POSITION_HIDDEN_LEFT_OR_TOP; newLocation = DIVIDER_POSITION_HIDDEN_LEFT_OR_TOP;
} else if (newLocation == splitPane.getMaximumDividerLocation()) { } else if (newLocation > splitPane.getMaximumDividerLocation()) {
newLocation = DIVIDER_POSITION_HIDDEN_RIGHT_OR_BOTTOM; newLocation = DIVIDER_POSITION_HIDDEN_RIGHT_OR_BOTTOM;
} }
allLocations.put(screenKey, newLocation); allLocations.put(screenKey, newLocation);
saveAllDividerLocations(allLocations, settingsKey); saveSplitterLocationsToSettings(allLocations, settingsKey);
} }
/** /**
@ -706,24 +713,25 @@ public final class GamePanel extends javax.swing.JPanel {
* @param settingsKey * @param settingsKey
* @param defaultProportion 0.25 means 25% for left component and 75% for right * @param defaultProportion 0.25 means 25% for left component and 75% for right
*/ */
private void restoreCurrentDividerLocation(JSplitPane splitPane, String settingsKey, double defaultProportion) { private void restoreSplitter(JSplitPane splitPane, String settingsKey, double defaultProportion) {
Map<String, Integer> allLocations = loadAllDividerLocations(settingsKey); Map<String, Integer> allLocations = loadSplitterLocationsFromSettings(settingsKey);
Rectangle screenRec = MageFrame.getDesktop().getBounds(); Rectangle screenRec = MageFrame.getDesktop().getBounds();
String screenKey = String.format("%d_x_%d", screenRec.width, screenRec.height); String screenKey = String.format("%d_x_%d", screenRec.width, screenRec.height);
// on first run it has nothing in saved values, so make sure to use default location (depends on inner components preferred sizes) // on first run it has nothing in saved values, so make sure to use default location (depends on inner components preferred sizes)
// WARNING, new divider location must be restored independently in swing threads // WARNING, new divider location must be restored independently in swing threads one by one
// (possible bug: size is zero until other dividers recalculated, e.g. game panel with hand + stack + chats)
int newLocation = allLocations.getOrDefault(screenKey, DIVIDER_POSITION_DEFAULT); int newLocation = allLocations.getOrDefault(screenKey, DIVIDER_POSITION_DEFAULT);
if (newLocation == DIVIDER_POSITION_DEFAULT) { if (newLocation == DIVIDER_POSITION_DEFAULT) {
// use default location // use default location
SwingUtilities.invokeLater(() -> { SwingUtilities.invokeLater(() -> {
splitPane.resetToPreferredSizes();
splitPane.setDividerLocation(defaultProportion); splitPane.setDividerLocation(defaultProportion);
}); });
} else if (newLocation == DIVIDER_POSITION_HIDDEN_LEFT_OR_TOP) { } else if (newLocation == DIVIDER_POSITION_HIDDEN_LEFT_OR_TOP) {
// use hidden (hide left) // use hidden (hide left)
SwingUtilities.invokeLater(() -> { SwingUtilities.invokeLater(() -> {
splitPane.resetToPreferredSizes();
splitPane.setDividerLocation(defaultProportion); splitPane.setDividerLocation(defaultProportion);
splitPane.getLeftComponent().setMinimumSize(new Dimension()); splitPane.getLeftComponent().setMinimumSize(new Dimension());
splitPane.setDividerLocation(0.0d); splitPane.setDividerLocation(0.0d);
@ -731,67 +739,56 @@ public final class GamePanel extends javax.swing.JPanel {
} else if (newLocation == DIVIDER_POSITION_HIDDEN_RIGHT_OR_BOTTOM) { } else if (newLocation == DIVIDER_POSITION_HIDDEN_RIGHT_OR_BOTTOM) {
// use hidden (hide right) // use hidden (hide right)
SwingUtilities.invokeLater(() -> { SwingUtilities.invokeLater(() -> {
splitPane.resetToPreferredSizes();
splitPane.setDividerLocation(defaultProportion); splitPane.setDividerLocation(defaultProportion);
splitPane.getLeftComponent().setMinimumSize(new Dimension()); splitPane.getRightComponent().setMinimumSize(new Dimension());
splitPane.setDividerLocation(1.0d); splitPane.setDividerLocation(1.0d);
}); });
} else { } else {
// use saved location // use saved location
SwingUtilities.invokeLater(() -> { SwingUtilities.invokeLater(() -> {
splitPane.resetToPreferredSizes();
splitPane.setDividerLocation(defaultProportion);
splitPane.setDividerLocation(newLocation); splitPane.setDividerLocation(newLocation);
}); });
} }
} }
public void restoreDividerLocations() { private void restoreSplitters() {
// split/divider locations must be restored after game panel will be visible, e.g. on game show // split/divider locations must be restored after game panel will be visible, e.g. on frame activated
isSplittersFullyRestored = false;
// TODO: migrate to new version SwingUtilities.invokeLater(() -> {
// restore for each screen size restoreSplittersByQueue(new LinkedHashMap<>(this.splitters));
Rectangle rec = MageFrame.getDesktop().getBounds(); });
// TODO: save for each size, not last only, need code research
String size = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_MAGE_PANEL_LAST_SIZE, null);
String sb = Double.toString(rec.getWidth()) + 'x' + rec.getHeight();
// use divider positions only if screen size is the same as it was the time the settings were saved
if (size != null && size.equals(sb)) {
String location = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_GAMEPANEL_DIVIDER_LOCATION_0, null);
if (location != null && jSplitPane0 != null) {
jSplitPane0.setDividerLocation(Integer.parseInt(location));
}
location = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_GAMEPANEL_DIVIDER_LOCATION_1, null);
if (location != null && jSplitPane1 != null) {
jSplitPane1.setDividerLocation(Integer.parseInt(location));
}
location = PreferencesDialog.getCachedValue(KEY_GAMEPANEL_DIVIDER_LOCATIONS_HAND_STACK, null);
if (location != null && jSplitPaneHandStack != null) {
// TODO: enable
//jSplitPaneHandStack.setDividerLocation(Integer.parseInt(location));
}
location = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_GAMEPANEL_DIVIDER_LOCATION_2, null);
if (location != null && jSplitPane2 != null) {
jSplitPane2.setDividerLocation(Integer.parseInt(location));
}
}
// new version
restoreCurrentDividerLocation(jSplitPaneHandStack, KEY_GAMEPANEL_DIVIDER_LOCATIONS_HAND_STACK, 0.70);
} }
private boolean isSmallMode() { private void restoreSplittersByQueue(Map<String, MageSplitter> splittersQueue) {
// TODO: no needs on gui scale, delete if (splittersQueue.isEmpty()) {
return this.getBounds().height < 770; isSplittersFullyRestored = true;
return;
}
// current
String currentKey = splittersQueue.keySet().stream().findFirst().get();
MageSplitter currentSplitter = splittersQueue.remove(currentKey);
restoreSplitter(currentSplitter.splitPane, currentKey, currentSplitter.defaultProportion);
// next in queue
SwingUtilities.invokeLater(() -> {
restoreSplittersByQueue(splittersQueue);
});
}
private void sizeBigCard() {
int width = bigCard.getParent().getWidth();
int height = Math.round(width * GUISizeHelper.CARD_WIDTH_TO_HEIGHT_COEF);
bigCard.setPreferredSize(new Dimension(width, height));
bigCard.setMaximumSize(new Dimension(Short.MAX_VALUE, height));
} }
private void sizeToScreen() { private void sizeToScreen() {
// on resize frame // on resize frame
Rectangle rect = this.getBounds(); Rectangle rect = this.getBounds();
Dimension bbDimension = new Dimension(256, 367);
bigCard.setMaximumSize(bbDimension);
bigCard.setMinimumSize(bbDimension);
bigCard.setPreferredSize(bbDimension);
pnlShortCuts.revalidate(); pnlShortCuts.revalidate();
for (PlayAreaPanel p : players.values()) { for (PlayAreaPanel p : players.values()) {
p.getPlayerPanel().sizePlayerPanel(false); p.getPlayerPanel().sizePlayerPanel(false);
@ -1029,7 +1026,7 @@ public final class GamePanel extends javax.swing.JPanel {
// set init sizes // set init sizes
for (PlayAreaPanel p : players.values()) { for (PlayAreaPanel p : players.values()) {
p.getPlayerPanel().sizePlayerPanel(isSmallMode()); p.getPlayerPanel().sizePlayerPanel(false);
} }
GridBagConstraints panelC = new GridBagConstraints(); GridBagConstraints panelC = new GridBagConstraints();
@ -1542,7 +1539,7 @@ public final class GamePanel extends javax.swing.JPanel {
public void onDeactivated() { public void onDeactivated() {
// save current dividers location // save current dividers location
saveDividerLocations(); saveSplitters();
// hide the non modal windows (because otherwise they are shown on top of the new active pane) // hide the non modal windows (because otherwise they are shown on top of the new active pane)
// TODO: is it need to hide other dialogs like graveyards (CardsView)? // TODO: is it need to hide other dialogs like graveyards (CardsView)?
@ -1572,7 +1569,7 @@ public final class GamePanel extends javax.swing.JPanel {
public void onActivated() { public void onActivated() {
// restore divider positions // restore divider positions
// must be called by swing after all pack and paint done (possible bug: zero size in restored divider) // must be called by swing after all pack and paint done (possible bug: zero size in restored divider)
SwingUtilities.invokeLater(this::restoreDividerLocations); SwingUtilities.invokeLater(this::restoreSplitters);
// hide the non modal windows (because otherwise they are shown on top of the new active pane) // hide the non modal windows (because otherwise they are shown on top of the new active pane)
for (CardInfoWindowDialog windowDialog : exiles.values()) { for (CardInfoWindowDialog windowDialog : exiles.values()) {
@ -2230,10 +2227,6 @@ public final class GamePanel extends javax.swing.JPanel {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private void initComponents() { private void initComponents() {
abilityPicker = new mage.client.components.ability.AbilityPicker(GUISizeHelper.dialogGuiScale); abilityPicker = new mage.client.components.ability.AbilityPicker(GUISizeHelper.dialogGuiScale);
jSplitPane1 = new javax.swing.JSplitPane();
jSplitPaneHandStack = new javax.swing.JSplitPane();
jSplitPane0 = new javax.swing.JSplitPane();
jPanel2 = new javax.swing.JPanel();
pnlHelperHandButtonsStackArea = new javax.swing.JPanel(); pnlHelperHandButtonsStackArea = new javax.swing.JPanel();
pnlShortCuts = new javax.swing.JPanel(); pnlShortCuts = new javax.swing.JPanel();
lblPhase = new javax.swing.JLabel(); lblPhase = new javax.swing.JLabel();
@ -2294,7 +2287,6 @@ public final class GamePanel extends javax.swing.JPanel {
gameChatPanel.setConnectedChat(userChatPanel); gameChatPanel.setConnectedChat(userChatPanel);
gameChatPanel.disableInput(); gameChatPanel.disableInput();
gameChatPanel.setMinimumSize(new java.awt.Dimension(100, 48)); gameChatPanel.setMinimumSize(new java.awt.Dimension(100, 48));
jSplitPane2 = new javax.swing.JSplitPane();
handContainer = new HandPanel(); handContainer = new HandPanel();
handCards = new HashMap<>(); handCards = new HashMap<>();
@ -2303,22 +2295,40 @@ public final class GamePanel extends javax.swing.JPanel {
stackObjects = new mage.client.cards.Cards(); stackObjects = new mage.client.cards.Cards();
jSplitPane1.setBorder(null); // split: [hand] <|> [stack]
jSplitPane1.setDividerSize(7); // TODO: add gui scale support? splitHandAndStack = new javax.swing.JSplitPane();
jSplitPane1.setResizeWeight(DIVIDER_KEEP_RIGHT_COMPONENT); splitHandAndStack.setBorder(null);
jSplitPane1.setOneTouchExpandable(true); splitHandAndStack.setResizeWeight(DIVIDER_KEEP_RIGHT_COMPONENT);
jSplitPane1.setMinimumSize(new java.awt.Dimension(26, 48)); // TODO: add gui scale support? splitHandAndStack.setOneTouchExpandable(true);
jSplitPaneHandStack.setBorder(null); // split: [game + chats] <|> [big card]
jSplitPaneHandStack.setDividerSize(7); splitGameAndBigCard = new javax.swing.JSplitPane();
jSplitPaneHandStack.setResizeWeight(DIVIDER_KEEP_RIGHT_COMPONENT); splitGameAndBigCard.setBorder(null);
jSplitPaneHandStack.setOneTouchExpandable(true); splitGameAndBigCard.setResizeWeight(DIVIDER_KEEP_RIGHT_COMPONENT);
jSplitPaneHandStack.setMinimumSize(new java.awt.Dimension(26, 48)); splitGameAndBigCard.setOneTouchExpandable(true);
jSplitPane0.setBorder(null); // split: chat <|> game logs
jSplitPane0.setDividerSize(7); splitChatAndLogs = new javax.swing.JSplitPane();
jSplitPane0.setResizeWeight(DIVIDER_KEEP_RIGHT_COMPONENT); splitChatAndLogs.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);
jSplitPane0.setOneTouchExpandable(true); splitChatAndLogs.setResizeWeight(DIVIDER_KEEP_LEFT_COMPONENT);
splitChatAndLogs.setTopComponent(userChatPanel);
splitChatAndLogs.setBottomComponent(gameChatPanel);
// split: [battlefield + hand + stack] <|> [chats]
splitBattlefieldAndChats = new javax.swing.JSplitPane();
splitBattlefieldAndChats.setBorder(null);
splitBattlefieldAndChats.setResizeWeight(DIVIDER_KEEP_RIGHT_COMPONENT);
splitBattlefieldAndChats.setOneTouchExpandable(true);
splitBattlefieldAndChats.setLeftComponent(pnlHelperHandButtonsStackArea);
splitBattlefieldAndChats.setRightComponent(splitChatAndLogs);
// warning, it's important to store/restore splitters in same order as real life GUI
// from outer to inner (otherwise panels will be hidden or weird)
// also it must be restored by thread queue
this.splitters.put(PreferencesDialog.KEY_GAMEPANEL_DIVIDER_LOCATIONS_GAME_AND_BIG_CARD, new MageSplitter(splitGameAndBigCard, 0.85));
this.splitters.put(PreferencesDialog.KEY_GAMEPANEL_DIVIDER_LOCATIONS_BATTLEFIELD_AND_CHATS, new MageSplitter(splitBattlefieldAndChats, 0.80));
this.splitters.put(PreferencesDialog.KEY_GAMEPANEL_DIVIDER_LOCATIONS_HAND_STACK, new MageSplitter(splitHandAndStack, 0.70));
this.splitters.put(PreferencesDialog.KEY_GAMEPANEL_DIVIDER_LOCATIONS_CHAT_AND_LOGS, new MageSplitter(splitChatAndLogs, 0.40));
lblPhase.setLabelFor(txtPhase); lblPhase.setLabelFor(txtPhase);
lblPhase.setText("Phase:"); lblPhase.setText("Phase:");
@ -2355,8 +2365,6 @@ public final class GamePanel extends javax.swing.JPanel {
lblPriority.setLabelFor(txtPriority); lblPriority.setLabelFor(txtPriority);
lblPriority.setText("Priority Player:"); lblPriority.setText("Priority Player:");
bigCard.setBorder(new LineBorder(Color.black, 1, true));
// CHATS and HINTS support // CHATS and HINTS support
// HOTKEYS // HOTKEYS
@ -2572,29 +2580,13 @@ public final class GamePanel extends javax.swing.JPanel {
this.getActionMap().put("ENLARGE_SOURCE", new AbstractAction() { this.getActionMap().put("ENLARGE_SOURCE", new AbstractAction() {
@Override @Override
public void actionPerformed(ActionEvent actionEvent) { public void actionPerformed(ActionEvent actionEvent) {
// TODO: doesn't work? 26.11.2023 // TODO: doesn't work? 26.11.2023, delete as useless
if (isUserImputActive()) return; if (isUserImputActive()) return;
ActionCallback callback = Plugins.instance.getActionCallback(); ActionCallback callback = Plugins.instance.getActionCallback();
((MageActionCallback) callback).enlargeCard(EnlargeMode.ALTERNATE); ((MageActionCallback) callback).enlargeCard(EnlargeMode.ALTERNATE);
} }
}); });
KeyStroke ksAltD = KeyStroke.getKeyStroke(KeyEvent.VK_D, InputEvent.ALT_MASK);
this.getInputMap(c).put(ksAltD, "BIG_IMAGE");
this.getActionMap().put("BIG_IMAGE", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent actionEvent) {
if (isUserImputActive()) return;
imagePanelState = !imagePanelState;
if (!imagePanelState) {
jSplitPane0.resetToPreferredSizes();
jSplitPane0.setDividerLocation(jSplitPane0.getSize().width - jSplitPane0.getInsets().right - jSplitPane0.getDividerSize() - 260);
} else {
jSplitPane0.setDividerLocation(1.0);
}
}
});
KeyStroke ksAlt1 = KeyStroke.getKeyStroke(KeyEvent.VK_1, InputEvent.ALT_MASK); KeyStroke ksAlt1 = KeyStroke.getKeyStroke(KeyEvent.VK_1, InputEvent.ALT_MASK);
this.getInputMap(c).put(ksAlt1, "USEFIRSTMANAABILITY"); this.getInputMap(c).put(ksAlt1, "USEFIRSTMANAABILITY");
this.getActionMap().put("USEFIRSTMANAABILITY", new AbstractAction() { this.getActionMap().put("USEFIRSTMANAABILITY", new AbstractAction() {
@ -2610,14 +2602,7 @@ public final class GamePanel extends javax.swing.JPanel {
} }
}); });
final BasicSplitPaneUI myUi = (BasicSplitPaneUI) jSplitPane0.getUI(); // TODO: delete as useless
final BasicSplitPaneDivider divider = myUi.getDivider();
final JButton upArrowButton = (JButton) divider.getComponent(0);
upArrowButton.addActionListener(actionEvent -> PreferencesDialog.saveValue(PreferencesDialog.KEY_BIG_CARD_TOGGLED, "up"));
final JButton downArrowButton = (JButton) divider.getComponent(1);
downArrowButton.addActionListener(actionEvent -> PreferencesDialog.saveValue(PreferencesDialog.KEY_BIG_CARD_TOGGLED, "down"));
KeyStroke ksAltEReleased = KeyStroke.getKeyStroke(KeyEvent.VK_E, InputEvent.ALT_MASK, true); KeyStroke ksAltEReleased = KeyStroke.getKeyStroke(KeyEvent.VK_E, InputEvent.ALT_MASK, true);
this.getInputMap(c).put(ksAltEReleased, "ENLARGE_RELEASE"); this.getInputMap(c).put(ksAltEReleased, "ENLARGE_RELEASE");
KeyStroke ksAltSReleased = KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.ALT_MASK, true); KeyStroke ksAltSReleased = KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.ALT_MASK, true);
@ -2705,55 +2690,20 @@ public final class GamePanel extends javax.swing.JPanel {
pnlReplay.setOpaque(false); pnlReplay.setOpaque(false);
jSplitPane2.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);
jSplitPane2.setResizeWeight(DIVIDER_KEEP_PROPORTION);
jSplitPane2.setLeftComponent(userChatPanel);
jSplitPane2.setBottomComponent(gameChatPanel);
// phases buttons // phases buttons
phasesContainer = new JPanel(new FlowLayout(FlowLayout.CENTER)); phasesContainer = new JPanel(new FlowLayout(FlowLayout.CENTER));
phasesContainer.setOpaque(false); phasesContainer.setOpaque(false);
phasesContainer.add(jPhases); phasesContainer.add(jPhases);
// split: battlefield <|> chats // card hint panel
jSplitPane1.setLeftComponent(pnlHelperHandButtonsStackArea); // TODO: research bigCardPanel = new javax.swing.JPanel();
jSplitPane1.setRightComponent(jSplitPane2); // TODO: reseach bigCardPanel.setOpaque(false);
bigCardPanel.setLayout(new BorderLayout());
// Set individual area sizes of big card pane bigCardPanel.add(bigCard, BorderLayout.NORTH);
// TODO: research - is it possible to use border layout without all custom code
GridBagLayout gbl = new GridBagLayout();
jPanel2.setLayout(gbl);
GridBagConstraints gbc = new GridBagConstraints();
gbc.fill = GridBagConstraints.BOTH;
gbc.gridx = 0;
gbc.gridy = 0;
gbc.gridwidth = 1;
gbc.gridheight = 4; // size 4/5
gbc.weightx = 1.0;
gbc.weighty = 1.0;
gbl.setConstraints(bigCard, gbc);
jPanel2.add(bigCard);
jPanel2.setOpaque(false);
// split: game <|> chat/log // split: game <|> chat/log
jSplitPane0.setLeftComponent(jSplitPane1); // TODO: research -- possible typo, must be jSplitPane1? splitGameAndBigCard.setLeftComponent(splitBattlefieldAndChats);
// big card and buttons splitGameAndBigCard.setRightComponent(bigCardPanel);
jSplitPane0.setRightComponent(jPanel2); // TODO: research
// TODO: need reseach, possible reason of weird scrolls restore
// TODO: remove
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jSplitPane0, javax.swing.GroupLayout.DEFAULT_SIZE, 1078, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jSplitPane0, javax.swing.GroupLayout.DEFAULT_SIZE, 798, Short.MAX_VALUE)
);
} }
private void removeListener() { private void removeListener() {
@ -2821,7 +2771,7 @@ public final class GamePanel extends javax.swing.JPanel {
this.btnSkipForward.removeActionListener(al); this.btnSkipForward.removeActionListener(al);
} }
final BasicSplitPaneUI myUi = (BasicSplitPaneUI) jSplitPane0.getUI(); final BasicSplitPaneUI myUi = (BasicSplitPaneUI) splitGameAndBigCard.getUI();
final BasicSplitPaneDivider divider = myUi.getDivider(); final BasicSplitPaneDivider divider = myUi.getDivider();
final JButton upArrowButton = (JButton) divider.getComponent(0); final JButton upArrowButton = (JButton) divider.getComponent(0);
for (ActionListener al : upArrowButton.getActionListeners()) { for (ActionListener al : upArrowButton.getActionListeners()) {
@ -3229,11 +3179,12 @@ public final class GamePanel extends javax.swing.JPanel {
private mage.client.game.FeedbackPanel feedbackPanel; private mage.client.game.FeedbackPanel feedbackPanel;
private HelperPanel helper; private HelperPanel helper;
private mage.client.chat.ChatPanelBasic userChatPanel; private mage.client.chat.ChatPanelBasic userChatPanel;
private javax.swing.JPanel jPanel2; private javax.swing.JPanel bigCardPanel;
private javax.swing.JPanel pnlHelperHandButtonsStackArea; private javax.swing.JPanel pnlHelperHandButtonsStackArea;
private javax.swing.JSplitPane jSplitPane0; private javax.swing.JSplitPane splitGameAndBigCard;
private javax.swing.JSplitPane jSplitPane1; private javax.swing.JSplitPane splitBattlefieldAndChats;
private javax.swing.JSplitPane jSplitPaneHandStack; private javax.swing.JSplitPane splitChatAndLogs;
private javax.swing.JSplitPane splitHandAndStack;
private javax.swing.JLabel lblActivePlayer; private javax.swing.JLabel lblActivePlayer;
private javax.swing.JLabel lblPhase; private javax.swing.JLabel lblPhase;
private javax.swing.JLabel lblPriority; private javax.swing.JLabel lblPriority;
@ -3253,7 +3204,6 @@ public final class GamePanel extends javax.swing.JPanel {
private mage.client.cards.Cards stackObjects; private mage.client.cards.Cards stackObjects;
private HandPanel handContainer; private HandPanel handContainer;
private javax.swing.JSplitPane jSplitPane2;
private JPanel jPhases; private JPanel jPhases;
private JPanel phasesContainer; private JPanel phasesContainer;
private javax.swing.JLabel txtHoldPriority; private javax.swing.JLabel txtHoldPriority;

View file

@ -115,6 +115,7 @@ public class TablesPane extends MagePane {
@Override @Override
public void deactivated() { public void deactivated() {
super.deactivated();
tablesPanel.stopTasks(); tablesPanel.stopTasks();
} }

View file

@ -87,7 +87,7 @@ public class TournamentPane extends MagePane {
@Override @Override
public void deactivated() { public void deactivated() {
super.deactivated();
tournamentPanel.stopTasks(); tournamentPanel.stopTasks();
} }
} }

View file

@ -22,6 +22,9 @@ public final class GUISizeHelper {
static final int CARD_IMAGE_HEIGHT = 445; static final int CARD_IMAGE_HEIGHT = 445;
static final int CARD_IMAG_VALUE = 42; static final int CARD_IMAG_VALUE = 42;
public static final float CARD_WIDTH_TO_HEIGHT_COEF = (1.0f * CARD_IMAGE_HEIGHT) / (1.0f * CARD_IMAGE_WIDTH);
public static final float CARD_HEIGHT_TO_WIDTH_COEF = (1.0f * CARD_IMAGE_WIDTH) / (1.0f * CARD_IMAGE_HEIGHT);
public static String basicSymbolSize = "small"; public static String basicSymbolSize = "small";
static final int MIN_FONT_SIZE = 7; static final int MIN_FONT_SIZE = 7;

View file

@ -17,6 +17,8 @@ import net.xeoh.plugins.base.annotations.events.PluginLoaded;
import net.xeoh.plugins.base.annotations.meta.Author; import net.xeoh.plugins.base.annotations.meta.Author;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
// TODO: delete as un-used and moved background images in main code
@PluginImplementation @PluginImplementation
@Author(name = "nantuko") @Author(name = "nantuko")
/* udpated by Noahsark */ /* udpated by Noahsark */
@ -83,8 +85,10 @@ public class ThemePluginImpl implements ThemePlugin {
ImagePanel bgPanel = new ImagePanel(backgroundImage, ImagePanelStyle.TILED); ImagePanel bgPanel = new ImagePanel(backgroundImage, ImagePanelStyle.TILED);
// TODO: research - is all components used? And why it make transparent? // TODO: research - is all components used? And why it make transparent?
unsetOpaque(ui.get("jSplitPane1")); unsetOpaque(ui.get("splitChatAndLogs"));
unsetOpaque(ui.get("jSplitPaneHandStack")); // TODO: miss jSplitPane0? unsetOpaque(ui.get("splitHandAndStack"));
unsetOpaque(ui.get("splitBattlefieldAndChats"));
unsetOpaque(ui.get("splitGameAndBigCard"));
unsetOpaque(ui.get("pnlBattlefield")); unsetOpaque(ui.get("pnlBattlefield"));
unsetOpaque(ui.get("pnlHelperHandButtonsStackArea")); unsetOpaque(ui.get("pnlHelperHandButtonsStackArea"));
unsetOpaque(ui.get("hand")); unsetOpaque(ui.get("hand"));