Fixed bug not updating UI after click on context menu item
fixes #11 Additionally, previous commit fixes #5
This commit is contained in:
parent
16a0786d54
commit
4959bc9634
@ -30,6 +30,7 @@ import envoy.client.data.commands.*;
|
||||
import envoy.client.event.*;
|
||||
import envoy.client.net.*;
|
||||
import envoy.client.ui.*;
|
||||
import envoy.client.ui.custom.TextInputContextMenu;
|
||||
import envoy.client.ui.listcell.*;
|
||||
import envoy.client.util.ReflectionUtil;
|
||||
import envoy.data.*;
|
||||
@ -168,6 +169,11 @@ public final class ChatScene implements EventListener, Restorable {
|
||||
messageList.setCellFactory(MessageListCell::new);
|
||||
chatList.setCellFactory(new ListCellFactory<>(ChatControl::new));
|
||||
|
||||
// JavaFX provides an internal way of populating the context menu of a textarea.
|
||||
// We, however, need additional functionality.
|
||||
messageTextArea.setContextMenu(new TextInputContextMenu(messageTextArea, e -> checkKeyCombination(null)));
|
||||
|
||||
// Set the icons of buttons and image views
|
||||
settingsButton.setGraphic(new ImageView(IconUtil.loadIconThemeSensitive("settings", DEFAULT_ICON_SIZE)));
|
||||
voiceButton.setGraphic(new ImageView(IconUtil.loadIconThemeSensitive("microphone", DEFAULT_ICON_SIZE)));
|
||||
attachmentButton.setGraphic(new ImageView(IconUtil.loadIconThemeSensitive("attachment", DEFAULT_ICON_SIZE)));
|
||||
@ -555,7 +561,10 @@ public final class ChatScene implements EventListener, Restorable {
|
||||
|
||||
// KeyPressed will be called before the char has been added to the text, hence
|
||||
// this is needed for the first char
|
||||
if (messageTextArea.getText().length() == 1) checkPostConditions(e);
|
||||
if (messageTextArea.getText().length() == 1 && e != null) checkPostConditions(e);
|
||||
|
||||
// This is needed for the messageTA context menu
|
||||
else if (e == null) checkPostConditions(false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -0,0 +1,109 @@
|
||||
package envoy.client.ui.custom;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import javafx.event.*;
|
||||
import javafx.scene.control.*;
|
||||
import javafx.scene.input.Clipboard;
|
||||
|
||||
/**
|
||||
* Displays a context menu that offers an additional option when one of
|
||||
* its menu items has been clicked.
|
||||
* <p>
|
||||
* Current options are:
|
||||
* <ul>
|
||||
* <li>undo</li>
|
||||
* <li>redo</li>
|
||||
* <li>cut</li>
|
||||
* <li>copy</li>
|
||||
* <li>paste</li>
|
||||
* <li>delete</li>
|
||||
* <li>clear</li>
|
||||
* <li>Select all</li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* Project: <strong>client</strong><br>
|
||||
* File: <strong>TextInputContextMenu.java</strong><br>
|
||||
* Created: <strong>20.09.2020</strong><br>
|
||||
*
|
||||
* @author Leon Hofmeister
|
||||
* @since Envoy Client v0.2-beta
|
||||
* @apiNote please refrain from using
|
||||
* {@link ContextMenu#setOnShowing(EventHandler)} as this is already
|
||||
* used by this component
|
||||
*/
|
||||
public class TextInputContextMenu extends ContextMenu {
|
||||
|
||||
private final MenuItem undoMI = new MenuItem("Undo");
|
||||
private final MenuItem redoMI = new MenuItem("Redo");
|
||||
private final MenuItem cutMI = new MenuItem("Cut");
|
||||
private final MenuItem copyMI = new MenuItem("Copy");
|
||||
private final MenuItem pasteMI = new MenuItem("Paste");
|
||||
private final MenuItem deleteMI = new MenuItem("Delete selection");
|
||||
private final MenuItem clearMI = new MenuItem("Clear");
|
||||
private final MenuItem selectAllMI = new MenuItem("Select all");
|
||||
private final MenuItem separatorMI = new SeparatorMenuItem();
|
||||
|
||||
/**
|
||||
* Creates a new {@code TextInputContextMenu} with an optional action when
|
||||
* this menu was clicked. Currently shows:
|
||||
* <ul>
|
||||
* <li>undo</li>
|
||||
* <li>redo</li>
|
||||
* <li>cut</li>
|
||||
* <li>copy</li>
|
||||
* <li>paste</li>
|
||||
* <li>delete</li>
|
||||
* <li>clear</li>
|
||||
* <li>Select all</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param control the text input component to display this
|
||||
* {@code ContextMenu}
|
||||
* @param menuItemClicked the second action to perform when a menu item of this
|
||||
* context menu has been clicked
|
||||
* @since Envoy Client v0.2-beta
|
||||
* @apiNote please refrain from using
|
||||
* {@link ContextMenu#setOnShowing(EventHandler)} as this is already
|
||||
* used by this component
|
||||
*/
|
||||
public TextInputContextMenu(TextInputControl control, Consumer<ActionEvent> menuItemClicked) {
|
||||
|
||||
// Define the actions when clicked
|
||||
undoMI.setOnAction(addAction(e -> control.undo(), menuItemClicked));
|
||||
redoMI.setOnAction(addAction(e -> control.redo(), menuItemClicked));
|
||||
cutMI.setOnAction(addAction(e -> control.cut(), menuItemClicked));
|
||||
copyMI.setOnAction(addAction(e -> control.copy(), menuItemClicked));
|
||||
pasteMI.setOnAction(addAction(e -> control.paste(), menuItemClicked));
|
||||
deleteMI.setOnAction(addAction(e -> control.replaceSelection(""), menuItemClicked));
|
||||
clearMI.setOnAction(addAction(e -> control.setText(""), menuItemClicked));
|
||||
selectAllMI.setOnAction(addAction(e -> control.selectAll(), menuItemClicked));
|
||||
|
||||
// Define the times it will be disabled
|
||||
undoMI.disableProperty().bind(control.undoableProperty().not());
|
||||
redoMI.disableProperty().bind(control.redoableProperty().not());
|
||||
cutMI.disableProperty().bind(control.selectedTextProperty().isEmpty());
|
||||
copyMI.disableProperty().bind(control.selectedTextProperty().isEmpty());
|
||||
deleteMI.disableProperty().bind(control.selectedTextProperty().isEmpty());
|
||||
clearMI.disableProperty().bind(control.textProperty().isEmpty());
|
||||
setOnShowing(e -> pasteMI.setDisable(!Clipboard.getSystemClipboard().hasString()));
|
||||
|
||||
selectAllMI.getProperties().put("refreshMenu", Boolean.TRUE);
|
||||
|
||||
// Add all items to the ContextMenu
|
||||
getItems().add(undoMI);
|
||||
getItems().add(redoMI);
|
||||
getItems().add(cutMI);
|
||||
getItems().add(copyMI);
|
||||
getItems().add(pasteMI);
|
||||
getItems().add(separatorMI);
|
||||
getItems().add(deleteMI);
|
||||
getItems().add(clearMI);
|
||||
getItems().add(separatorMI);
|
||||
getItems().add(selectAllMI);
|
||||
}
|
||||
|
||||
private EventHandler<ActionEvent> addAction(Consumer<ActionEvent> originalAction, Consumer<ActionEvent> additionalAction) {
|
||||
return e -> { originalAction.accept(e); additionalAction.accept(e); };
|
||||
}
|
||||
}
|
@ -1,8 +1,7 @@
|
||||
package envoy.data;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
import envoy.data.Message.MessageStatus;
|
||||
|
||||
@ -80,21 +79,15 @@ public final class MessageBuilder {
|
||||
* Creates an instance of {@link Message} with the previously supplied values.
|
||||
* If a mandatory value is not set, a default value will be used instead:<br>
|
||||
* <br>
|
||||
* <table border="1">
|
||||
* <tr>
|
||||
* <td>{@code date}</td>
|
||||
* <td>{@code Instant.now()} and {@code null} for {@code receivedDate} and
|
||||
* {@code readDate}</td>
|
||||
* <tr>
|
||||
* <tr>
|
||||
* <td>{@code text}</td>
|
||||
* <td>{@code ""}</td>
|
||||
* <tr>
|
||||
* <tr>
|
||||
* <td>{@code status}</td>
|
||||
* <td>{@code MessageStatus.WAITING}</td>
|
||||
* <tr>
|
||||
* </table>
|
||||
* {@code date}
|
||||
* {@code Instant.now()} and {@code null} for {@code receivedDate} and
|
||||
* {@code readDate}
|
||||
* <br>
|
||||
* {@code text}
|
||||
* {@code ""}
|
||||
* <br>
|
||||
* {@code status}
|
||||
* {@code MessageStatus.WAITING}
|
||||
*
|
||||
* @return a new instance of {@link Message}
|
||||
* @since Envoy Common v0.2-alpha
|
||||
@ -111,16 +104,12 @@ public final class MessageBuilder {
|
||||
* If a mandatory value is not set, a default value will be used
|
||||
* instead:<br>
|
||||
* <br>
|
||||
* <table border="1">
|
||||
* <tr>
|
||||
* <td>{@code time stamp}</td>
|
||||
* <td>{@code Instant.now()}</td>
|
||||
* <tr>
|
||||
* <tr>
|
||||
* <td>{@code text}</td>
|
||||
* <td>{@code ""}</td>
|
||||
* <tr>
|
||||
* </table>
|
||||
* {@code time stamp}
|
||||
* {@code Instant.now()}
|
||||
* <br>
|
||||
* {@code text}
|
||||
* {@code ""}
|
||||
* <br>
|
||||
*
|
||||
* @param group the {@link Group} that is used to fill the map of member
|
||||
* statuses
|
||||
@ -138,16 +127,11 @@ public final class MessageBuilder {
|
||||
* values. If a mandatory value is not set, a default value will be used
|
||||
* instead:<br>
|
||||
* <br>
|
||||
* <table border="1">
|
||||
* <tr>
|
||||
* <td>{@code time stamp}</td>
|
||||
* <td>{@code Instant.now()}</td>
|
||||
* <tr>
|
||||
* <tr>
|
||||
* <td>{@code text}</td>
|
||||
* <td>{@code ""}</td>
|
||||
* <tr>
|
||||
* </table>
|
||||
* {@code time stamp}
|
||||
* {@code Instant.now()}
|
||||
* <br>
|
||||
* {@code text}
|
||||
* {@code ""}
|
||||
*
|
||||
* @param group the {@link Group} that is used to fill the map of
|
||||
* member statuses
|
||||
|
Reference in New Issue
Block a user