195 lines
7.2 KiB
Java
195 lines
7.2 KiB
Java
package envoy.client.ui.chatscene;
|
|
|
|
import java.util.Random;
|
|
import java.util.function.*;
|
|
import java.util.logging.Level;
|
|
|
|
import javafx.scene.control.*;
|
|
import javafx.scene.control.Alert.AlertType;
|
|
import javafx.scene.control.skin.VirtualFlow;
|
|
|
|
import envoy.data.Message;
|
|
import envoy.data.User.UserStatus;
|
|
import envoy.util.EnvoyLog;
|
|
|
|
import envoy.client.data.Context;
|
|
import envoy.client.data.commands.*;
|
|
import envoy.client.helper.ShutdownHelper;
|
|
import envoy.client.ui.SceneInfo;
|
|
import envoy.client.ui.controller.ChatScene;
|
|
import envoy.client.util.*;
|
|
|
|
/**
|
|
* Contains all {@link SystemCommand}s used for {@link envoy.client.ui.controller.ChatScene}.
|
|
*
|
|
* @author Leon Hofmeister
|
|
* @since Envoy Client v0.3-beta
|
|
*/
|
|
public final class ChatSceneCommands {
|
|
|
|
private final ListView<Message> messageList;
|
|
private final SystemCommandMap messageTextAreaCommands = new SystemCommandMap();
|
|
private final SystemCommandBuilder builder =
|
|
new SystemCommandBuilder(messageTextAreaCommands);
|
|
|
|
private static final String messageDependentCommandDescription =
|
|
" the given message. Use s/S to use the selected message. Otherwise expects a number relative to the uppermost completely visible message.";
|
|
|
|
/**
|
|
* @param messageList the message list to use for some commands
|
|
* @param chatScene the instance of {@code ChatScene} that uses this object
|
|
* @since Envoy Client v0.3-beta
|
|
*/
|
|
public ChatSceneCommands(ListView<Message> messageList, ChatScene chatScene) {
|
|
this.messageList = messageList;
|
|
|
|
// Error message initialization
|
|
builder.setAction(text -> { throw new RuntimeException(); })
|
|
.setDescription("Shows an error message.").buildNoArg("error");
|
|
|
|
// Do A Barrel roll initialization
|
|
final var random = new Random();
|
|
builder
|
|
.setAction(text -> chatScene.doABarrelRoll(Integer.parseInt(text.get(0)),
|
|
Double.parseDouble(text.get(1))))
|
|
.setDefaults(Integer.toString(random.nextInt(3) + 1),
|
|
Double.toString(random.nextDouble() * 3 + 1))
|
|
.setDescription("See for yourself :)")
|
|
.setNumberOfArguments(2)
|
|
.build("dabr");
|
|
|
|
// Logout initialization
|
|
builder.setAction(text -> UserUtil.logout()).setDescription("Logs you out.")
|
|
.buildNoArg("logout");
|
|
|
|
// Exit initialization
|
|
builder.setAction(text -> ShutdownHelper.exit()).setNumberOfArguments(0)
|
|
.setDescription("Exits the program.").build("exit", false);
|
|
builder.build("q");
|
|
|
|
// Open settings scene initialization
|
|
builder
|
|
.setAction(
|
|
text -> Context.getInstance().getSceneContext().load(SceneInfo.SETTINGS_SCENE))
|
|
.setDescription("Opens the settings screen")
|
|
.buildNoArg("settings");
|
|
|
|
// Status change initialization
|
|
builder.setAction(text -> {
|
|
try {
|
|
UserUtil.changeStatus(Enum.valueOf(UserStatus.class, text.get(0).toUpperCase()));
|
|
} catch (final IllegalArgumentException e) {
|
|
final var alert = new Alert(AlertType.ERROR);
|
|
alert.setContentText("Please provide an existing status");
|
|
alert.showAndWait();
|
|
}
|
|
}).setDescription("Changes your status to the given status.").setNumberOfArguments(1)
|
|
.setDefaults("").build("status");
|
|
|
|
// Selection of a new message initialization
|
|
messageDependantAction("s",
|
|
m -> {
|
|
messageList.getSelectionModel().clearSelection();
|
|
messageList.getSelectionModel().select(m);
|
|
},
|
|
m -> true,
|
|
"Selects");
|
|
|
|
// Copy text of selection initialization
|
|
messageDependantAction("cp", MessageUtil::copyMessageText, m -> !m.getText().isEmpty(),
|
|
"Copies the text of");
|
|
|
|
// Delete selection initialization
|
|
messageDependantAction("del", MessageUtil::deleteMessage, m -> true, "Deletes");
|
|
|
|
// Save attachment of selection initialization
|
|
messageDependantAction("save-att", MessageUtil::saveAttachment, Message::hasAttachment,
|
|
"Saves the attachment of");
|
|
}
|
|
|
|
private void messageDependantAction(String command, Consumer<Message> action,
|
|
Predicate<Message> additionalCheck, String description) {
|
|
builder.setAction(text -> {
|
|
final var positionalArgument = text.get(0).toLowerCase();
|
|
|
|
// the currently selected message was requested
|
|
if (positionalArgument.startsWith("s")) {
|
|
final var relativeString =
|
|
positionalArgument.length() == 1 ? "" : positionalArgument.substring(1);
|
|
|
|
// Only s has been used as input
|
|
if (positionalArgument.length() == 1) {
|
|
final var selectedMessage = messageList.getSelectionModel().getSelectedItem();
|
|
if (selectedMessage != null && additionalCheck.test(selectedMessage))
|
|
action.accept(selectedMessage);
|
|
return;
|
|
|
|
// Either s++ or s-- has been requested
|
|
} else if (relativeString.equals("++") || relativeString.equals("--"))
|
|
selectionNeighbor(action, additionalCheck, positionalArgument);
|
|
|
|
// A message relative to the currently selected message should be used (i.e.
|
|
// s+4)
|
|
else
|
|
useRelativeMessage(command, action, additionalCheck, relativeString, true);
|
|
|
|
// Either ++s or --s has been requested
|
|
} else if (positionalArgument.equals("--s") || positionalArgument.equals("++s"))
|
|
selectionNeighbor(action, additionalCheck, positionalArgument);
|
|
|
|
// Just a number is expected: ((+)4)
|
|
else
|
|
useRelativeMessage(command, action, additionalCheck, positionalArgument, false);
|
|
}).setDefaults("s").setNumberOfArguments(1)
|
|
.setDescription(description.concat(messageDependentCommandDescription)).build(command);
|
|
}
|
|
|
|
private void selectionNeighbor(Consumer<Message> action, Predicate<Message> additionalCheck,
|
|
final String positionalArgument) {
|
|
final var wantedIndex = messageList.getSelectionModel().getSelectedIndex()
|
|
+ (positionalArgument.contains("+") ? 1 : -1);
|
|
messageList.getSelectionModel().clearAndSelect(wantedIndex);
|
|
final var selectedMessage = messageList.getItems().get(wantedIndex);
|
|
if (selectedMessage != null && additionalCheck.test(selectedMessage))
|
|
action.accept(selectedMessage);
|
|
}
|
|
|
|
private void useRelativeMessage(String command, Consumer<Message> action,
|
|
Predicate<Message> additionalCheck, final String positionalArgument,
|
|
boolean useSelectedMessage) throws NumberFormatException {
|
|
final var stripPlus =
|
|
positionalArgument.startsWith("+") ? positionalArgument.substring(1)
|
|
: positionalArgument;
|
|
final var incDec = Integer.valueOf(stripPlus);
|
|
try {
|
|
|
|
// The currently selected message is the base message
|
|
if (useSelectedMessage) {
|
|
final var messageToUse = messageList.getItems()
|
|
.get(messageList.getSelectionModel().getSelectedIndex() + incDec);
|
|
if (messageToUse != null && additionalCheck.test(messageToUse))
|
|
action.accept(messageToUse);
|
|
|
|
// The currently upmost completely visible message is the base message
|
|
} else {
|
|
final var messageToUse = messageList.getItems()
|
|
.get(((VirtualFlow<?>) messageList.lookup(".virtual-flow"))
|
|
.getFirstVisibleCell().getIndex() + 1 + incDec);
|
|
if (messageToUse != null && additionalCheck.test(messageToUse))
|
|
action.accept(messageToUse);
|
|
}
|
|
} catch (final IndexOutOfBoundsException e) {
|
|
EnvoyLog.getLogger(ChatSceneCommands.class)
|
|
.log(Level.INFO,
|
|
" A non-existing message was requested by the user for System command "
|
|
+ command);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @return the map used by this {@code ChatSceneCommands}
|
|
* @since Envoy Client v0.3-beta
|
|
*/
|
|
public SystemCommandMap getChatSceneCommands() { return messageTextAreaCommands; }
|
|
}
|