Add Voice Recording to ChatScene
The ChatScene layout has been adjusted to include a voice message button. When pressed, a recording starts. To finish the recording, press the button again. The recording will be saved as a pending attachment. The next message sent will include the attachment. When a pending attachment is present, a message can be sent without text. When the chat is switched, the pending attachment is discarded. This does not stop active recordings, however. The ChatScene layout handles large stages better now by ditching percentage-wise row and column scaling in favor of absolute values for all cells except the message list and text area.
This commit is contained in:
parent
0abd5cf17c
commit
60d3e65574
@ -17,9 +17,7 @@ import javafx.scene.input.KeyCode;
|
|||||||
import javafx.scene.input.KeyEvent;
|
import javafx.scene.input.KeyEvent;
|
||||||
import javafx.scene.paint.Color;
|
import javafx.scene.paint.Color;
|
||||||
|
|
||||||
import envoy.client.data.Chat;
|
import envoy.client.data.*;
|
||||||
import envoy.client.data.LocalDB;
|
|
||||||
import envoy.client.data.Settings;
|
|
||||||
import envoy.client.event.MessageCreationEvent;
|
import envoy.client.event.MessageCreationEvent;
|
||||||
import envoy.client.net.Client;
|
import envoy.client.net.Client;
|
||||||
import envoy.client.net.WriteProxy;
|
import envoy.client.net.WriteProxy;
|
||||||
@ -29,10 +27,12 @@ import envoy.client.ui.listcell.ContactListCellFactory;
|
|||||||
import envoy.client.ui.listcell.MessageControl;
|
import envoy.client.ui.listcell.MessageControl;
|
||||||
import envoy.client.ui.listcell.MessageListCellFactory;
|
import envoy.client.ui.listcell.MessageListCellFactory;
|
||||||
import envoy.data.*;
|
import envoy.data.*;
|
||||||
|
import envoy.data.Attachment.AttachmentType;
|
||||||
import envoy.event.EventBus;
|
import envoy.event.EventBus;
|
||||||
import envoy.event.MessageStatusChange;
|
import envoy.event.MessageStatusChange;
|
||||||
import envoy.event.UserStatusChange;
|
import envoy.event.UserStatusChange;
|
||||||
import envoy.event.contact.ContactOperation;
|
import envoy.event.contact.ContactOperation;
|
||||||
|
import envoy.exception.EnvoyException;
|
||||||
import envoy.util.EnvoyLog;
|
import envoy.util.EnvoyLog;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -57,6 +57,9 @@ public final class ChatScene {
|
|||||||
@FXML
|
@FXML
|
||||||
private Button postButton;
|
private Button postButton;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private Button voiceButton;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private Button settingsButton;
|
private Button settingsButton;
|
||||||
|
|
||||||
@ -77,9 +80,11 @@ public final class ChatScene {
|
|||||||
private WriteProxy writeProxy;
|
private WriteProxy writeProxy;
|
||||||
private SceneContext sceneContext;
|
private SceneContext sceneContext;
|
||||||
|
|
||||||
private boolean postingPermanentlyDisabled = false;
|
private Chat currentChat;
|
||||||
|
private AudioRecorder recorder;
|
||||||
private Chat currentChat;
|
private boolean recording;
|
||||||
|
private Attachment pendingAttachment;
|
||||||
|
private boolean postingPermanentlyDisabled = false;
|
||||||
|
|
||||||
private static final Settings settings = Settings.getInstance();
|
private static final Settings settings = Settings.getInstance();
|
||||||
private static final EventBus eventBus = EventBus.getInstance();
|
private static final EventBus eventBus = EventBus.getInstance();
|
||||||
@ -171,6 +176,9 @@ public final class ChatScene {
|
|||||||
contactLabel.setText(localDB.getUser().getName());
|
contactLabel.setText(localDB.getUser().getName());
|
||||||
MessageControl.setUser(localDB.getUser());
|
MessageControl.setUser(localDB.getUser());
|
||||||
if (!client.isOnline()) updateInfoLabel("You are offline", "infoLabel-info");
|
if (!client.isOnline()) updateInfoLabel("You are offline", "infoLabel-info");
|
||||||
|
|
||||||
|
recorder = new AudioRecorder();
|
||||||
|
if (!recorder.isSupported()) voiceButton.setDisable(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -201,6 +209,10 @@ public final class ChatScene {
|
|||||||
logger.log(Level.WARNING, "Could not read current chat.", e);
|
logger.log(Level.WARNING, "Could not read current chat.", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Discard the pending attachment
|
||||||
|
// TODO: stop running recording
|
||||||
|
pendingAttachment = null;
|
||||||
|
|
||||||
remainingChars.setVisible(true);
|
remainingChars.setVisible(true);
|
||||||
remainingChars
|
remainingChars
|
||||||
.setText(String.format("remaining chars: %d/%d", MAX_MESSAGE_LENGTH - messageTextArea.getText().length(), MAX_MESSAGE_LENGTH));
|
.setText(String.format("remaining chars: %d/%d", MAX_MESSAGE_LENGTH - messageTextArea.getText().length(), MAX_MESSAGE_LENGTH));
|
||||||
@ -230,6 +242,25 @@ public final class ChatScene {
|
|||||||
sceneContext.<ContactSearchScene>getController().initializeData(sceneContext, localDB);
|
sceneContext.<ContactSearchScene>getController().initializeData(sceneContext, localDB);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private void voiceButtonClicked() {
|
||||||
|
new Thread(() -> {
|
||||||
|
try {
|
||||||
|
if (!recording) {
|
||||||
|
recording = true;
|
||||||
|
Platform.runLater(() -> voiceButton.setText("Recording..."));
|
||||||
|
recorder.start();
|
||||||
|
} else {
|
||||||
|
pendingAttachment = new Attachment(recorder.finish(), AttachmentType.VOICE);
|
||||||
|
recording = false;
|
||||||
|
Platform.runLater(() -> { voiceButton.setText("Record Voice Message"); checkPostConditions(false); });
|
||||||
|
}
|
||||||
|
} catch (EnvoyException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks the text length of the {@code messageTextArea}, adjusts the
|
* Checks the text length of the {@code messageTextArea}, adjusts the
|
||||||
* {@code remainingChars} label and checks whether to send the message
|
* {@code remainingChars} label and checks whether to send the message
|
||||||
@ -252,11 +283,15 @@ public final class ChatScene {
|
|||||||
*/
|
*/
|
||||||
@FXML
|
@FXML
|
||||||
private void checkPostConditions(KeyEvent e) {
|
private void checkPostConditions(KeyEvent e) {
|
||||||
|
checkPostConditions(settings.isEnterToSend() && e.getCode() == KeyCode.ENTER
|
||||||
|
|| !settings.isEnterToSend() && e.getCode() == KeyCode.ENTER && e.isControlDown());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkPostConditions(boolean sendKeyPressed) {
|
||||||
if (!postingPermanentlyDisabled) {
|
if (!postingPermanentlyDisabled) {
|
||||||
if (!postButton.isDisabled() && (settings.isEnterToSend() && e.getCode() == KeyCode.ENTER
|
if (!postButton.isDisabled() && sendKeyPressed)
|
||||||
|| !settings.isEnterToSend() && e.getCode() == KeyCode.ENTER && e.isControlDown()))
|
|
||||||
postMessage();
|
postMessage();
|
||||||
postButton.setDisable(messageTextArea.getText().isBlank() || currentChat == null);
|
postButton.setDisable((messageTextArea.getText().isBlank() && pendingAttachment == null) || currentChat == null);
|
||||||
} else {
|
} else {
|
||||||
final var noMoreMessaging = "Go online to send messages";
|
final var noMoreMessaging = "Go online to send messages";
|
||||||
if (!infoLabel.getText().equals(noMoreMessaging))
|
if (!infoLabel.getText().equals(noMoreMessaging))
|
||||||
@ -311,12 +346,14 @@ public final class ChatScene {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final var text = messageTextArea.getText().strip();
|
final var text = messageTextArea.getText().strip();
|
||||||
if (text.isBlank()) throw new IllegalArgumentException("A message without visible text can not be sent.");
|
|
||||||
try {
|
try {
|
||||||
// Create and send message
|
// Create and send message
|
||||||
final var message = new MessageBuilder(localDB.getUser().getID(), currentChat.getRecipient().getID(), localDB.getIDGenerator())
|
var builder = new MessageBuilder(localDB.getUser().getID(), currentChat.getRecipient().getID(), localDB.getIDGenerator()).setText(text);
|
||||||
.setText(text)
|
if (pendingAttachment != null) {
|
||||||
.build();
|
builder.setAttachment(pendingAttachment);
|
||||||
|
pendingAttachment = null;
|
||||||
|
}
|
||||||
|
var message = builder.build();
|
||||||
|
|
||||||
// Send message
|
// Send message
|
||||||
writeProxy.writeMessage(message);
|
writeProxy.writeMessage(message);
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
<?import javafx.geometry.Insets?>
|
<?import javafx.geometry.Insets?>
|
||||||
<?import javafx.scene.control.Button?>
|
<?import javafx.scene.control.Button?>
|
||||||
|
<?import javafx.scene.control.ButtonBar?>
|
||||||
<?import javafx.scene.control.ContextMenu?>
|
<?import javafx.scene.control.ContextMenu?>
|
||||||
<?import javafx.scene.control.Label?>
|
<?import javafx.scene.control.Label?>
|
||||||
<?import javafx.scene.control.ListView?>
|
<?import javafx.scene.control.ListView?>
|
||||||
@ -12,40 +13,21 @@
|
|||||||
<?import javafx.scene.layout.GridPane?>
|
<?import javafx.scene.layout.GridPane?>
|
||||||
<?import javafx.scene.layout.RowConstraints?>
|
<?import javafx.scene.layout.RowConstraints?>
|
||||||
|
|
||||||
<GridPane hgap="5.0" maxHeight="-Infinity" maxWidth="-Infinity"
|
<GridPane hgap="5.0" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="400.0" minWidth="350.0" prefHeight="400.0" prefWidth="600.0" vgap="2.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="envoy.client.ui.controller.ChatScene">
|
||||||
minHeight="400.0" minWidth="350.0" prefHeight="400.0" prefWidth="600.0"
|
|
||||||
vgap="2.0" xmlns="http://javafx.com/javafx/11.0.1"
|
|
||||||
xmlns:fx="http://javafx.com/fxml/1"
|
|
||||||
fx:controller="envoy.client.ui.controller.ChatScene">
|
|
||||||
<columnConstraints>
|
<columnConstraints>
|
||||||
<ColumnConstraints hgrow="SOMETIMES"
|
<ColumnConstraints hgrow="NEVER" minWidth="60.0" prefWidth="160.0" />
|
||||||
maxWidth="1.7976931348623157E308" minWidth="10.0" percentWidth="25.0"
|
<ColumnConstraints hgrow="ALWAYS" maxWidth="1.7976931348623157E308" minWidth="10.0" prefWidth="357.0" />
|
||||||
prefWidth="161.0" />
|
|
||||||
<ColumnConstraints hgrow="SOMETIMES"
|
|
||||||
maxWidth="1.7976931348623157E308" minWidth="10.0" percentWidth="65.0"
|
|
||||||
prefWidth="357.0" />
|
|
||||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="10.0"
|
|
||||||
minWidth="10.0" percentWidth="10.0" prefWidth="10.0" />
|
|
||||||
</columnConstraints>
|
</columnConstraints>
|
||||||
<rowConstraints>
|
<rowConstraints>
|
||||||
<RowConstraints maxHeight="1.7976931348623157E308"
|
<RowConstraints maxHeight="-Infinity" minHeight="-Infinity" prefHeight="50.0" vgrow="NEVER" />
|
||||||
minHeight="10.0" percentHeight="10.0" prefHeight="70.0"
|
<RowConstraints maxHeight="-Infinity" minHeight="-Infinity" prefHeight="20.0" vgrow="NEVER" />
|
||||||
vgrow="SOMETIMES" />
|
<RowConstraints maxHeight="1.7976931348623157E308" minHeight="50.0" prefHeight="155.14286150251115" vgrow="ALWAYS" />
|
||||||
<RowConstraints maxHeight="1.7976931348623157E308"
|
<RowConstraints maxHeight="-Infinity" minHeight="-Infinity" prefHeight="20.0" vgrow="NEVER" />
|
||||||
minHeight="10.0" percentHeight="7.0" vgrow="SOMETIMES" />
|
<RowConstraints maxHeight="120.0" minHeight="40.0" prefHeight="60.0" vgrow="NEVER" />
|
||||||
<RowConstraints maxHeight="1.7976931348623157E308"
|
<RowConstraints maxHeight="-Infinity" minHeight="-Infinity" prefHeight="40.0" vgrow="NEVER" />
|
||||||
minHeight="10.0" percentHeight="60.0" prefHeight="50.0"
|
|
||||||
vgrow="SOMETIMES" />
|
|
||||||
<RowConstraints maxHeight="50.0" minHeight="10.0"
|
|
||||||
percentHeight="2.0" prefHeight="50.0" vgrow="SOMETIMES" />
|
|
||||||
<RowConstraints maxHeight="1.7976931348623157E308"
|
|
||||||
minHeight="10.0" percentHeight="21.0" prefHeight="100.0"
|
|
||||||
vgrow="SOMETIMES" />
|
|
||||||
</rowConstraints>
|
</rowConstraints>
|
||||||
<children>
|
<children>
|
||||||
<ListView fx:id="userList" onMouseClicked="#userListClicked"
|
<ListView fx:id="userList" onMouseClicked="#userListClicked" prefHeight="211.0" prefWidth="300.0" GridPane.rowIndex="1" GridPane.rowSpan="2147483647">
|
||||||
prefHeight="211.0" prefWidth="300.0" GridPane.rowIndex="1"
|
|
||||||
GridPane.rowSpan="2147483647">
|
|
||||||
<GridPane.margin>
|
<GridPane.margin>
|
||||||
<Insets bottom="10.0" left="10.0" />
|
<Insets bottom="10.0" left="10.0" />
|
||||||
</GridPane.margin>
|
</GridPane.margin>
|
||||||
@ -55,14 +37,12 @@
|
|||||||
<contextMenu>
|
<contextMenu>
|
||||||
<ContextMenu anchorLocation="CONTENT_TOP_LEFT">
|
<ContextMenu anchorLocation="CONTENT_TOP_LEFT">
|
||||||
<items>
|
<items>
|
||||||
<MenuItem fx:id="deleteContactMenuItem"
|
<MenuItem fx:id="deleteContactMenuItem" mnemonicParsing="false" onAction="#deleteContact" text="Delete" />
|
||||||
mnemonicParsing="false" onAction="#deleteContact" text="Delete" />
|
|
||||||
</items>
|
</items>
|
||||||
</ContextMenu>
|
</ContextMenu>
|
||||||
</contextMenu>
|
</contextMenu>
|
||||||
</ListView>
|
</ListView>
|
||||||
<Label fx:id="contactLabel" prefHeight="16.0" prefWidth="250.0"
|
<Label fx:id="contactLabel" prefHeight="27.0" prefWidth="134.0" GridPane.columnSpan="2">
|
||||||
text="Select a contact to chat with" GridPane.columnSpan="2">
|
|
||||||
<GridPane.margin>
|
<GridPane.margin>
|
||||||
<Insets left="10.0" />
|
<Insets left="10.0" />
|
||||||
</GridPane.margin>
|
</GridPane.margin>
|
||||||
@ -70,10 +50,7 @@
|
|||||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
||||||
</padding>
|
</padding>
|
||||||
</Label>
|
</Label>
|
||||||
<Button fx:id="settingsButton" mnemonicParsing="true"
|
<Button fx:id="settingsButton" mnemonicParsing="true" onAction="#settingsButtonClicked" text="_Settings" GridPane.columnIndex="1" GridPane.halignment="RIGHT" GridPane.valignment="CENTER">
|
||||||
onAction="#settingsButtonClicked" text="_Settings"
|
|
||||||
GridPane.columnIndex="1" GridPane.columnSpan="2"
|
|
||||||
GridPane.halignment="RIGHT" GridPane.valignment="CENTER">
|
|
||||||
<GridPane.margin>
|
<GridPane.margin>
|
||||||
<Insets bottom="10.0" right="10.0" top="10.0" />
|
<Insets bottom="10.0" right="10.0" top="10.0" />
|
||||||
</GridPane.margin>
|
</GridPane.margin>
|
||||||
@ -81,10 +58,7 @@
|
|||||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
||||||
</padding>
|
</padding>
|
||||||
</Button>
|
</Button>
|
||||||
<ListView fx:id="messageList" prefHeight="257.0"
|
<ListView fx:id="messageList" prefHeight="257.0" prefWidth="465.0" GridPane.columnIndex="1" GridPane.columnSpan="2147483647" GridPane.rowIndex="1" GridPane.rowSpan="2">
|
||||||
prefWidth="465.0" GridPane.columnIndex="1"
|
|
||||||
GridPane.columnSpan="2147483647" GridPane.rowIndex="1"
|
|
||||||
GridPane.rowSpan="2">
|
|
||||||
<GridPane.margin>
|
<GridPane.margin>
|
||||||
<Insets left="5.0" right="10.0" />
|
<Insets left="5.0" right="10.0" />
|
||||||
</GridPane.margin>
|
</GridPane.margin>
|
||||||
@ -94,74 +68,55 @@
|
|||||||
<contextMenu>
|
<contextMenu>
|
||||||
<ContextMenu anchorLocation="CONTENT_TOP_LEFT">
|
<ContextMenu anchorLocation="CONTENT_TOP_LEFT">
|
||||||
<items>
|
<items>
|
||||||
<MenuItem mnemonicParsing="false" onAction="#copyMessage"
|
<MenuItem mnemonicParsing="false" onAction="#copyMessage" text="Copy" />
|
||||||
text="Copy" />
|
<MenuItem mnemonicParsing="false" onAction="#deleteMessage" text="Delete" />
|
||||||
<MenuItem mnemonicParsing="false"
|
<MenuItem mnemonicParsing="false" onAction="#forwardMessage" text="Forward" />
|
||||||
onAction="#deleteMessage" text="Delete" />
|
<MenuItem mnemonicParsing="false" onAction="#quoteMessage" text="Quote" />
|
||||||
<MenuItem mnemonicParsing="false"
|
<MenuItem mnemonicParsing="false" onAction="#loadMessageInfoScene" text="Info" />
|
||||||
onAction="#forwardMessage" text="Forward" />
|
|
||||||
<MenuItem mnemonicParsing="false"
|
|
||||||
onAction="#quoteMessage" text="Quote" />
|
|
||||||
<MenuItem mnemonicParsing="false"
|
|
||||||
onAction="#loadMessageInfoScene" text="Info" />
|
|
||||||
</items>
|
</items>
|
||||||
</ContextMenu>
|
</ContextMenu>
|
||||||
</contextMenu>
|
</contextMenu>
|
||||||
</ListView>
|
</ListView>
|
||||||
<Button fx:id="postButton" defaultButton="true" disable="true"
|
<ButtonBar prefWidth="436.0" GridPane.columnIndex="1" GridPane.halignment="CENTER" GridPane.rowIndex="5" GridPane.valignment="BOTTOM">
|
||||||
mnemonicParsing="true" onAction="#postMessage" prefHeight="10.0"
|
<GridPane.margin>
|
||||||
prefWidth="75.0" text="_Post" GridPane.columnIndex="2"
|
<Insets right="10.0" top="5.0" />
|
||||||
GridPane.halignment="CENTER" GridPane.rowIndex="4"
|
</GridPane.margin>
|
||||||
GridPane.valignment="BOTTOM">
|
<buttons>
|
||||||
|
<Button fx:id="voiceButton" onAction="#voiceButtonClicked" text="_Record Voice Message" />
|
||||||
|
<Button fx:id="postButton" defaultButton="true" disable="true" mnemonicParsing="true" onAction="#postMessage" prefHeight="10.0" prefWidth="75.0" text="_Post">
|
||||||
|
<tooltip>
|
||||||
|
<Tooltip anchorLocation="WINDOW_TOP_LEFT" autoHide="true" maxWidth="350.0" text="Click this button to send the message. If it is disabled, you first have to select a contact to send it to. A message may automatically be sent when you press (Ctrl + ) Enter, according to your preferences. Additionally sends a message when pressing "Alt" + "P"." wrapText="true" />
|
||||||
|
</tooltip>
|
||||||
|
<contextMenu>
|
||||||
|
<ContextMenu anchorLocation="CONTENT_TOP_LEFT">
|
||||||
|
<items>
|
||||||
|
<MenuItem mnemonicParsing="false" onAction="#copyAndPostMessage" text="Copy and Send" />
|
||||||
|
</items>
|
||||||
|
</ContextMenu>
|
||||||
|
</contextMenu>
|
||||||
|
<padding>
|
||||||
|
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
||||||
|
</padding>
|
||||||
|
</Button>
|
||||||
|
</buttons>
|
||||||
|
</ButtonBar>
|
||||||
|
<TextArea fx:id="messageTextArea" disable="true" onInputMethodTextChanged="#messageTextUpdated" onKeyPressed="#checkPostConditions" onKeyTyped="#checkKeyCombination" prefHeight="200.0" prefWidth="200.0" wrapText="true" GridPane.columnIndex="1" GridPane.rowIndex="4">
|
||||||
<GridPane.margin>
|
<GridPane.margin>
|
||||||
<Insets bottom="10.0" right="10.0" />
|
<Insets bottom="10.0" left="5.0" right="10.0" top="3.0" />
|
||||||
</GridPane.margin>
|
|
||||||
<tooltip>
|
|
||||||
<Tooltip anchorLocation="WINDOW_TOP_LEFT" autoHide="true"
|
|
||||||
maxWidth="350.0"
|
|
||||||
text="Click this button to send the message. If it is disabled, you first have to select a contact to send it to. A message may automatically be sent when you press (Ctrl + ) Enter, according to your preferences. Additionally sends a message when pressing "Alt" + "P"."
|
|
||||||
wrapText="true" />
|
|
||||||
</tooltip>
|
|
||||||
<contextMenu>
|
|
||||||
<ContextMenu anchorLocation="CONTENT_TOP_LEFT">
|
|
||||||
<items>
|
|
||||||
<MenuItem mnemonicParsing="false"
|
|
||||||
onAction="#copyAndPostMessage" text="Copy and Send" />
|
|
||||||
</items>
|
|
||||||
</ContextMenu>
|
|
||||||
</contextMenu>
|
|
||||||
<padding>
|
|
||||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
|
||||||
</padding>
|
|
||||||
</Button>
|
|
||||||
<TextArea fx:id="messageTextArea" disable="true"
|
|
||||||
onInputMethodTextChanged="#messageTextUpdated"
|
|
||||||
onKeyPressed="#checkPostConditions" onKeyTyped="#checkKeyCombination"
|
|
||||||
prefHeight="200.0" prefWidth="200.0" wrapText="true"
|
|
||||||
GridPane.columnIndex="1" GridPane.rowIndex="4">
|
|
||||||
<GridPane.margin>
|
|
||||||
<Insets bottom="10.0" left="5.0" top="3.0" />
|
|
||||||
</GridPane.margin>
|
</GridPane.margin>
|
||||||
<opaqueInsets>
|
<opaqueInsets>
|
||||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
||||||
</opaqueInsets>
|
</opaqueInsets>
|
||||||
</TextArea>
|
</TextArea>
|
||||||
<Button mnemonicParsing="true"
|
<Button mnemonicParsing="true" onAction="#addContactButtonClicked" text="_Add Contacts" GridPane.halignment="CENTER" GridPane.rowIndex="5" GridPane.valignment="CENTER">
|
||||||
onAction="#addContactButtonClicked" text="_Add Contacts"
|
|
||||||
GridPane.halignment="CENTER" GridPane.rowIndex="4"
|
|
||||||
GridPane.valignment="CENTER">
|
|
||||||
<padding>
|
<padding>
|
||||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
||||||
</padding>
|
</padding>
|
||||||
<GridPane.margin>
|
<GridPane.margin>
|
||||||
<Insets bottom="5.0" left="10.0" right="5.0" top="5.0" />
|
<Insets bottom="10.0" left="10.0" right="5.0" top="5.0" />
|
||||||
</GridPane.margin>
|
</GridPane.margin>
|
||||||
</Button>
|
</Button>
|
||||||
<Label id="remainingCharsLabel" fx:id="remainingChars"
|
<Label id="remainingCharsLabel" fx:id="remainingChars" ellipsisString="" maxHeight="30.0" maxWidth="180.0" prefHeight="30.0" prefWidth="180.0" text="remaining chars: 0/x" textFill="LIME" textOverrun="LEADING_WORD_ELLIPSIS" visible="false" GridPane.columnIndex="1" GridPane.rowIndex="3">
|
||||||
ellipsisString="" maxHeight="30.0" maxWidth="180.0" prefHeight="30.0"
|
|
||||||
prefWidth="180.0" text="remaining chars: 0/x" textFill="LIME"
|
|
||||||
textOverrun="LEADING_WORD_ELLIPSIS" visible="false"
|
|
||||||
GridPane.columnIndex="1" GridPane.rowIndex="3">
|
|
||||||
<GridPane.margin>
|
<GridPane.margin>
|
||||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
||||||
</GridPane.margin>
|
</GridPane.margin>
|
||||||
@ -172,14 +127,10 @@
|
|||||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
||||||
</opaqueInsets>
|
</opaqueInsets>
|
||||||
<tooltip>
|
<tooltip>
|
||||||
<Tooltip
|
<Tooltip text="Shows how many chars you can still enter in this message" wrapText="true" />
|
||||||
text="Shows how many chars you can still enter in this message"
|
|
||||||
wrapText="true" />
|
|
||||||
</tooltip>
|
</tooltip>
|
||||||
</Label>
|
</Label>
|
||||||
<Label fx:id="infoLabel" text="Something happened"
|
<Label fx:id="infoLabel" text="Something happened" textFill="#faa007" visible="false" wrapText="true" GridPane.columnIndex="1" GridPane.rowIndex="1">
|
||||||
wrapText="true" textFill="#faa007" visible="false"
|
|
||||||
GridPane.columnIndex="1" GridPane.rowIndex="1">
|
|
||||||
<GridPane.margin>
|
<GridPane.margin>
|
||||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
||||||
</GridPane.margin>
|
</GridPane.margin>
|
||||||
|
Reference in New Issue
Block a user