GUI: improved feedback needed sound notifications (plays only for inactive game or app, see #6853);

This commit is contained in:
Oleg Agafonov 2020-07-31 20:00:36 +04:00
parent c343767e8e
commit 610baac6ab
6 changed files with 828 additions and 804 deletions

View file

@ -1639,6 +1639,13 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
whatsNewDialog.checkUpdatesAndShow(forceToShowPage);
}
}
public boolean isGameFrameActive(UUID gameId) {
if (activeFrame != null && activeFrame instanceof GamePane) {
return ((GamePane) activeFrame).getGameId().equals(gameId);
}
return false;
}
}
class MagePaneMenuItem extends JCheckBoxMenuItem {

View file

@ -5,40 +5,39 @@
*
* Created on Jan 7, 2011, 2:15:48 PM
*/
package mage.client.draft;
package mage.client.draft;
import mage.cards.repository.CardInfo;
import mage.cards.repository.CardRepository;
import mage.client.MageFrame;
import mage.client.SessionHandler;
import mage.client.components.tray.MageTray;
import mage.client.deckeditor.SortSettingDraft;
import mage.client.dialog.PreferencesDialog;
import mage.client.plugins.impl.Plugins;
import mage.client.util.*;
import mage.client.util.Event;
import mage.client.util.audio.AudioManager;
import mage.client.util.gui.BufferedImageBuilder;
import mage.constants.PlayerAction;
import mage.view.*;
import mage.cards.repository.CardInfo;
import mage.cards.repository.CardRepository;
import mage.client.MageFrame;
import mage.client.SessionHandler;
import mage.client.components.tray.MageTray;
import mage.client.deckeditor.SortSettingDraft;
import mage.client.dialog.PreferencesDialog;
import mage.client.plugins.impl.Plugins;
import mage.client.util.Event;
import mage.client.util.*;
import mage.client.util.audio.AudioManager;
import mage.client.util.gui.BufferedImageBuilder;
import mage.constants.PlayerAction;
import mage.view.*;
import javax.swing.*;
import javax.swing.Timer;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.List;
import javax.swing.Timer;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.*;
/**
*
* @author BetaSteward_at_googlemail.com
*/
public class DraftPanel extends javax.swing.JPanel {
public class DraftPanel extends javax.swing.JPanel {
private UUID draftId;
private Timer countdown;
@ -285,7 +284,7 @@ public class DraftPanel extends javax.swing.JPanel {
}
);
setMessage("Pick a card");
if (!MageFrame.getInstance().isActive()) {
if (!AppUtil.isAppActive()) {
MageTray.instance.displayMessage("Pick the next card.");
MageTray.instance.blink();
}
@ -408,7 +407,7 @@ public class DraftPanel extends javax.swing.JPanel {
if (currentBooster != null) {
String lastPick = getCardName(getLastPick(pickView.getPicks().values()));
if (lastPick != null && currentBooster.length > 1) {
draftLogger.logPick(getCurrentSetCode(), packNo, pickNo-1, lastPick, currentBooster);
draftLogger.logPick(getCurrentSetCode(), packNo, pickNo - 1, lastPick, currentBooster);
}
currentBooster = null;
}
@ -420,7 +419,7 @@ public class DraftPanel extends javax.swing.JPanel {
private String getCurrentSetCode() {
if (!setCodes.isEmpty()) {
return setCodes.get(packNo-1);
return setCodes.get(packNo - 1);
} else {
return "";
}
@ -861,4 +860,4 @@ public class DraftPanel extends javax.swing.JPanel {
private javax.swing.JTextField txtTimeRemaining;
// End of variables declaration//GEN-END:variables
}
}

View file

@ -1,19 +1,5 @@
/*
* FeedbackPanel.java
*
* Created on 23-Dec-2009, 9:54:01 PM
*/
package mage.client.game;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import mage.client.MageFrame;
import mage.client.SessionHandler;
import mage.client.chat.ChatPanelBasic;
@ -21,15 +7,22 @@ import mage.client.dialog.MageDialog;
import mage.client.util.GUISizeHelper;
import mage.client.util.audio.AudioManager;
import mage.client.util.gui.ArrowBuilder;
import static mage.constants.Constants.Option.ORIGINAL_ID;
import static mage.constants.Constants.Option.SECOND_MESSAGE;
import static mage.constants.Constants.Option.SPECIAL_BUTTON;
import mage.constants.PlayerAction;
import mage.constants.TurnPhase;
import org.apache.log4j.Logger;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.io.Serializable;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import static mage.constants.Constants.Option.*;
/**
*
* @author BetaSteward_at_googlemail.com
*/
public class FeedbackPanel extends javax.swing.JPanel {
@ -45,7 +38,6 @@ public class FeedbackPanel extends javax.swing.JPanel {
private MageDialog connectedDialog;
private ChatPanelBasic connectedChatPanel;
private int lastMessageId;
private LocalDateTime lastResponse;
private static final ScheduledExecutorService WORKER = Executors.newSingleThreadScheduledExecutor();
@ -86,12 +78,6 @@ public class FeedbackPanel extends javax.swing.JPanel {
this.helper.setTextArea(lblText);
//this.lblMessage.setText(lblText);
// Alert user when needing feedback if last dialog was informative, and it has been over 2 seconds since last input
if (this.mode == FeedbackMode.INFORM && mode != FeedbackMode.INFORM
&& (this.lastResponse == null || this.lastResponse.isBefore(LocalDateTime.now().minusSeconds(2)))) {
AudioManager.playFeedbackNeeded();
}
this.mode = mode;
switch (this.mode) {
case INFORM:
@ -251,7 +237,6 @@ public class FeedbackPanel extends javax.swing.JPanel {
}
private void btnRightActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnRightActionPerformed
setLastResponse();
if (connectedDialog != null) {
connectedDialog.removeDialog();
connectedDialog = null;
@ -270,18 +255,15 @@ public class FeedbackPanel extends javax.swing.JPanel {
}//GEN-LAST:event_btnRightActionPerformed
private void btnLeftActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnLeftActionPerformed
setLastResponse();
SessionHandler.sendPlayerBoolean(gameId, true);
AudioManager.playButtonCancel();
}//GEN-LAST:event_btnLeftActionPerformed
private void btnSpecialActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnSpecialActionPerformed
setLastResponse();
SessionHandler.sendPlayerString(gameId, "special");
}//GEN-LAST:event_btnSpecialActionPerformed
private void btnUndoActionPerformed(java.awt.event.ActionEvent evt) {
setLastResponse();
SessionHandler.sendPlayerAction(PlayerAction.UNDO, gameId, null);
}
@ -313,10 +295,6 @@ public class FeedbackPanel extends javax.swing.JPanel {
this.helper.setUndoEnabled(false);
}
public void setLastResponse() {
this.lastResponse = LocalDateTime.now();
}
private javax.swing.JButton btnLeft;
private javax.swing.JButton btnRight;
private javax.swing.JButton btnSpecial;

View file

@ -18,7 +18,6 @@ import mage.client.dialog.CardInfoWindowDialog.ShowType;
import mage.client.game.FeedbackPanel.FeedbackMode;
import mage.client.plugins.adapters.MageActionCallback;
import mage.client.plugins.impl.Plugins;
import mage.client.themes.ThemeType;
import mage.client.util.Event;
import mage.client.util.*;
import mage.client.util.audio.AudioManager;
@ -2355,7 +2354,6 @@ public final class GamePanel extends javax.swing.JPanel {
}
private void btnEndTurnActionPerformed(java.awt.event.ActionEvent evt) {
this.feedbackPanel.setLastResponse();
SessionHandler.sendPlayerAction(PlayerAction.PASS_PRIORITY_UNTIL_NEXT_TURN, gameId, null);
skipButtons.activateSkipButton(KEY_CONTROL_NEXT_TURN);
@ -2379,7 +2377,6 @@ public final class GamePanel extends javax.swing.JPanel {
}
private void btnUntilEndOfTurnActionPerformed(java.awt.event.ActionEvent evt) {
this.feedbackPanel.setLastResponse();
SessionHandler.sendPlayerAction(PlayerAction.PASS_PRIORITY_UNTIL_TURN_END_STEP, gameId, null);
skipButtons.activateSkipButton(KEY_CONTROL_END_STEP);
@ -2397,7 +2394,6 @@ public final class GamePanel extends javax.swing.JPanel {
}
private void btnUntilNextMainPhaseActionPerformed(java.awt.event.ActionEvent evt) {
this.feedbackPanel.setLastResponse();
SessionHandler.sendPlayerAction(PlayerAction.PASS_PRIORITY_UNTIL_NEXT_MAIN_PHASE, gameId, null);
skipButtons.activateSkipButton(KEY_CONTROL_MAIN_STEP);
@ -2406,7 +2402,6 @@ public final class GamePanel extends javax.swing.JPanel {
}
private void btnPassPriorityUntilNextYourTurnActionPerformed(java.awt.event.ActionEvent evt) {
this.feedbackPanel.setLastResponse();
SessionHandler.sendPlayerAction(PlayerAction.PASS_PRIORITY_UNTIL_MY_NEXT_TURN, gameId, null);
skipButtons.activateSkipButton(KEY_CONTROL_YOUR_TURN);
@ -2415,7 +2410,6 @@ public final class GamePanel extends javax.swing.JPanel {
}
private void btnPassPriorityUntilStackResolvedActionPerformed(java.awt.event.ActionEvent evt) {
this.feedbackPanel.setLastResponse();
SessionHandler.sendPlayerAction(PlayerAction.PASS_PRIORITY_UNTIL_STACK_RESOLVED, gameId, null);
skipButtons.activateSkipButton(KEY_CONTROL_SKIP_STACK);
@ -2424,7 +2418,6 @@ public final class GamePanel extends javax.swing.JPanel {
}
private void btnSkipToEndStepBeforeYourTurnActionPerformed(java.awt.event.ActionEvent evt) {
this.feedbackPanel.setLastResponse();
SessionHandler.sendPlayerAction(PlayerAction.PASS_PRIORITY_UNTIL_END_STEP_BEFORE_MY_NEXT_TURN, gameId, null);
skipButtons.activateSkipButton(KEY_CONTROL_PRIOR_END);
@ -2433,7 +2426,6 @@ public final class GamePanel extends javax.swing.JPanel {
}
private void restorePriorityActionPerformed(java.awt.event.ActionEvent evt) {
this.feedbackPanel.setLastResponse();
SessionHandler.sendPlayerAction(PlayerAction.PASS_PRIORITY_CANCEL_ALL_ACTIONS, gameId, null);
skipButtons.activateSkipButton("");

View file

@ -1,4 +1,3 @@
package mage.client.game;
import mage.client.SessionHandler;
@ -6,7 +5,9 @@ import mage.client.components.MageTextArea;
import mage.client.constants.Constants;
import mage.client.dialog.PreferencesDialog;
import mage.client.game.FeedbackPanel.FeedbackMode;
import mage.client.util.AppUtil;
import mage.client.util.GUISizeHelper;
import mage.client.util.audio.AudioManager;
import mage.constants.TurnPhase;
import javax.swing.*;
@ -64,6 +65,18 @@ public class HelperPanel extends JPanel {
private boolean gameNeedFeedback = false;
private TurnPhase gameTurnPhase = null;
private Timer needFeedbackTimer;
{
// start timer to inform user about needed feedback (example: inform by sound play)
needFeedbackTimer = new Timer(100, evt -> SwingUtilities.invokeLater(() -> {
needFeedbackTimer.stop();
if (!AppUtil.isAppActive() || !AppUtil.isGameActive(this.gameId)) {
AudioManager.playFeedbackNeeded();
}
}));
}
public HelperPanel() {
initComponents();
}
@ -297,7 +310,7 @@ public class HelperPanel extends JPanel {
public void autoSizeButtonsAndFeedbackState() {
// two mode: same size for small texts (flow), different size for long texts (grid)
// plus colorize feedback panel on player's priority
// also colorize feedback panel on player's priority and enable sound notification
int BUTTONS_H_GAP = 15;
Color ACTIVE_FEEDBACK_BACKGROUND_COLOR_MAIN = new Color(0, 0, 255, 50);
@ -325,6 +338,10 @@ public class HelperPanel extends JPanel {
// color panel on player's feedback waiting
if (this.gameNeedFeedback) {
// start notification sound timer
this.needFeedbackTimer.restart();
// wait player's action
switch (FEEDBACK_COLORIZING_MODE) {
case Constants.BATTLEFIELD_FEEDBACK_COLORIZING_MODE_DISABLE:
@ -362,6 +379,9 @@ public class HelperPanel extends JPanel {
break;
}
} else {
// stop notification sound timer
this.needFeedbackTimer.stop();
// inform about other players
this.mainPanel.setOpaque(false);
}

View file

@ -0,0 +1,28 @@
package mage.client.util;
import mage.client.MageFrame;
import java.util.UUID;
/**
* @author JayDi85
*/
public class AppUtil {
/**
* Application is active in operation system (got user focus)
*/
public static boolean isAppActive() {
return MageFrame.getInstance().isActive();
}
/**
* Current active panel is game panel (e.g. the user sees the checking game)
*
* @param gameId game to check
* @return
*/
public static boolean isGameActive(UUID gameId) {
return MageFrame.getInstance().isGameFrameActive(gameId);
}
}