Merge pull request 'Display Current User Status and Unread Message Amount in Status Tray Icon' (#103) from f/enhanced-status-tray-icon into develop
Reviewed-on: https://git.kske.dev/zdm/envoy/pulls/103 Reviewed-by: delvh <leon@kske.dev> Reviewed-by: DieGurke <maxi@kske.dev>
This commit is contained in:
commit
889e9b186f
@ -3,6 +3,7 @@ package envoy.client.data;
|
|||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
import javafx.beans.property.*;
|
||||||
import javafx.collections.*;
|
import javafx.collections.*;
|
||||||
|
|
||||||
import envoy.data.*;
|
import envoy.data.*;
|
||||||
@ -21,18 +22,20 @@ import envoy.client.net.WriteProxy;
|
|||||||
*/
|
*/
|
||||||
public class Chat implements Serializable {
|
public class Chat implements Serializable {
|
||||||
|
|
||||||
protected transient ObservableList<Message> messages = FXCollections.observableArrayList();
|
|
||||||
|
|
||||||
protected int unreadAmount;
|
|
||||||
protected boolean disabled;
|
protected boolean disabled;
|
||||||
|
|
||||||
protected final Contact recipient;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores the last time an {@link envoy.event.IsTyping} event has been sent.
|
* Stores the last time an {@link envoy.event.IsTyping} event has been sent.
|
||||||
*/
|
*/
|
||||||
protected transient long lastWritingEvent;
|
protected transient long lastWritingEvent;
|
||||||
|
|
||||||
|
protected transient ObservableList<Message> messages = FXCollections.observableArrayList();
|
||||||
|
|
||||||
|
protected int unreadAmount;
|
||||||
|
protected static IntegerProperty totalUnreadAmount = new SimpleIntegerProperty();
|
||||||
|
|
||||||
|
protected final Contact recipient;
|
||||||
|
|
||||||
private static final long serialVersionUID = 2L;
|
private static final long serialVersionUID = 2L;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -50,6 +53,7 @@ public class Chat implements Serializable {
|
|||||||
private void readObject(ObjectInputStream stream) throws ClassNotFoundException, IOException {
|
private void readObject(ObjectInputStream stream) throws ClassNotFoundException, IOException {
|
||||||
stream.defaultReadObject();
|
stream.defaultReadObject();
|
||||||
messages = FXCollections.observableList((List<Message>) stream.readObject());
|
messages = FXCollections.observableList((List<Message>) stream.readObject());
|
||||||
|
totalUnreadAmount.set(totalUnreadAmount.get() + unreadAmount);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeObject(ObjectOutputStream stream) throws IOException {
|
private void writeObject(ObjectOutputStream stream) throws IOException {
|
||||||
@ -111,6 +115,7 @@ public class Chat implements Serializable {
|
|||||||
writeProxy.writeMessageStatusChange(new MessageStatusChange(m));
|
writeProxy.writeMessageStatusChange(new MessageStatusChange(m));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
totalUnreadAmount.set(totalUnreadAmount.get() - unreadAmount);
|
||||||
unreadAmount = 0;
|
unreadAmount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,6 +155,12 @@ public class Chat implements Serializable {
|
|||||||
return messages.removeIf(m -> m.getID() == messageID);
|
return messages.removeIf(m -> m.getID() == messageID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return an integer property storing the total amount of unread messages
|
||||||
|
* @since Envoy Client v0.3-beta
|
||||||
|
*/
|
||||||
|
public static IntegerProperty getTotalUnreadAmount() { return totalUnreadAmount; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Increments the amount of unread messages.
|
* Increments the amount of unread messages.
|
||||||
*
|
*
|
||||||
@ -157,6 +168,7 @@ public class Chat implements Serializable {
|
|||||||
*/
|
*/
|
||||||
public void incrementUnreadAmount() {
|
public void incrementUnreadAmount() {
|
||||||
++unreadAmount;
|
++unreadAmount;
|
||||||
|
totalUnreadAmount.set(totalUnreadAmount.get() + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -147,6 +147,7 @@ public final class LocalDB implements EventListener {
|
|||||||
throw new IllegalStateException("Client user is null, cannot initialize user storage");
|
throw new IllegalStateException("Client user is null, cannot initialize user storage");
|
||||||
userFile = new File(dbDir, user.getID() + ".db");
|
userFile = new File(dbDir, user.getID() + ".db");
|
||||||
try (var in = new ObjectInputStream(new FileInputStream(userFile))) {
|
try (var in = new ObjectInputStream(new FileInputStream(userFile))) {
|
||||||
|
Chat.getTotalUnreadAmount().set(0);
|
||||||
chats = FXCollections.observableList((List<Chat>) in.readObject());
|
chats = FXCollections.observableList((List<Chat>) in.readObject());
|
||||||
|
|
||||||
// Some chats have changed and should not be overwritten by the saved values
|
// Some chats have changed and should not be overwritten by the saved values
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package envoy.client.data;
|
package envoy.client.data;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.function.Consumer;
|
|
||||||
|
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
|
|
||||||
@ -17,8 +16,6 @@ public final class SettingsItem<T> implements Serializable {
|
|||||||
private T value;
|
private T value;
|
||||||
private String userFriendlyName, description;
|
private String userFriendlyName, description;
|
||||||
|
|
||||||
private transient Consumer<T> changeHandler;
|
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -52,8 +49,6 @@ public final class SettingsItem<T> implements Serializable {
|
|||||||
* @since Envoy Client v0.3-alpha
|
* @since Envoy Client v0.3-alpha
|
||||||
*/
|
*/
|
||||||
public void set(T value) {
|
public void set(T value) {
|
||||||
if (changeHandler != null && value != this.value)
|
|
||||||
changeHandler.accept(value);
|
|
||||||
this.value = value;
|
this.value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,16 +77,4 @@ public final class SettingsItem<T> implements Serializable {
|
|||||||
* @since Envoy Client v0.3-alpha
|
* @since Envoy Client v0.3-alpha
|
||||||
*/
|
*/
|
||||||
public void setDescription(String description) { this.description = description; }
|
public void setDescription(String description) { this.description = description; }
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets a {@code ChangeHandler} for this {@link SettingsItem}. It will be invoked with the
|
|
||||||
* current value once during the registration and every time when the value changes.
|
|
||||||
*
|
|
||||||
* @param changeHandler the changeHandler to set
|
|
||||||
* @since Envoy Client v0.3-alpha
|
|
||||||
*/
|
|
||||||
public void setChangeHandler(Consumer<T> changeHandler) {
|
|
||||||
this.changeHandler = changeHandler;
|
|
||||||
changeHandler.accept(value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -237,17 +237,9 @@ public final class Startup extends Application {
|
|||||||
e.consume();
|
e.consume();
|
||||||
});
|
});
|
||||||
|
|
||||||
if (StatusTrayIcon.isSupported()) {
|
|
||||||
|
|
||||||
// Initialize status tray icon
|
// Initialize status tray icon
|
||||||
final var trayIcon = new StatusTrayIcon(stage);
|
if (StatusTrayIcon.isSupported())
|
||||||
Settings.getInstance().getItems().get("hideOnClose").setChangeHandler(c -> {
|
new StatusTrayIcon(stage).show();
|
||||||
if ((Boolean) c)
|
|
||||||
trayIcon.show();
|
|
||||||
else
|
|
||||||
trayIcon.hide();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start auto save thread
|
// Start auto save thread
|
||||||
localDB.initAutoSave();
|
localDB.initAutoSave();
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
package envoy.client.ui;
|
package envoy.client.ui;
|
||||||
|
|
||||||
|
import static java.awt.Image.SCALE_SMOOTH;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.TrayIcon.MessageType;
|
import java.awt.TrayIcon.MessageType;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import javafx.stage.Stage;
|
import javafx.stage.Stage;
|
||||||
@ -12,11 +15,19 @@ import dev.kske.eventbus.Event;
|
|||||||
import envoy.data.Message;
|
import envoy.data.Message;
|
||||||
import envoy.data.User.UserStatus;
|
import envoy.data.User.UserStatus;
|
||||||
|
|
||||||
import envoy.client.event.OwnStatusChange;
|
import envoy.client.data.*;
|
||||||
|
import envoy.client.event.*;
|
||||||
import envoy.client.helper.ShutdownHelper;
|
import envoy.client.helper.ShutdownHelper;
|
||||||
import envoy.client.util.*;
|
import envoy.client.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* A tray icon with the Envoy logo, an "Envoy" tool tip and a pop-up menu with menu items for
|
||||||
|
* <ul>
|
||||||
|
* <li>Changing the user status</li>
|
||||||
|
* <li>Logging out</li>
|
||||||
|
* <li>Quitting Envoy</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
* @author Kai S. K. Engelbart
|
* @author Kai S. K. Engelbart
|
||||||
* @since Envoy Client v0.2-alpha
|
* @since Envoy Client v0.2-alpha
|
||||||
*/
|
*/
|
||||||
@ -32,7 +43,20 @@ public final class StatusTrayIcon implements EventListener {
|
|||||||
* A received {@link Message} is only displayed as a system tray notification if this variable
|
* A received {@link Message} is only displayed as a system tray notification if this variable
|
||||||
* is set to {@code true}.
|
* is set to {@code true}.
|
||||||
*/
|
*/
|
||||||
private boolean displayMessages;
|
private boolean displayMessageNotification;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The size of the tray icon's image.
|
||||||
|
*/
|
||||||
|
private final Dimension size;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Envoy logo on which the current user status and unread message count will be drawn to
|
||||||
|
* compose the tray icon.
|
||||||
|
*/
|
||||||
|
private final Image logo;
|
||||||
|
|
||||||
|
private static final Font unreadMessageFont = new Font("sans-serif", Font.PLAIN, 8);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return {@code true} if the status tray icon is supported on this platform
|
* @return {@code true} if the status tray icon is supported on this platform
|
||||||
@ -47,9 +71,9 @@ public final class StatusTrayIcon implements EventListener {
|
|||||||
* @since Envoy Client v0.2-beta
|
* @since Envoy Client v0.2-beta
|
||||||
*/
|
*/
|
||||||
public StatusTrayIcon(Stage stage) {
|
public StatusTrayIcon(Stage stage) {
|
||||||
trayIcon = new TrayIcon(IconUtil.loadAWTCompatible("/icons/envoy_logo.png"), "Envoy");
|
size = SystemTray.getSystemTray().getTrayIconSize();
|
||||||
trayIcon.setImageAutoSize(true);
|
logo = IconUtil.loadAWTCompatible("/icons/envoy_logo.png").getScaledInstance(size.width,
|
||||||
trayIcon.setToolTip("You are notified if you have unread messages.");
|
size.height, SCALE_SMOOTH);
|
||||||
|
|
||||||
final var popup = new PopupMenu();
|
final var popup = new PopupMenu();
|
||||||
|
|
||||||
@ -60,10 +84,7 @@ public final class StatusTrayIcon implements EventListener {
|
|||||||
|
|
||||||
// Adding the logout menu item
|
// Adding the logout menu item
|
||||||
final var logoutMenuItem = new MenuItem("Logout");
|
final var logoutMenuItem = new MenuItem("Logout");
|
||||||
logoutMenuItem.addActionListener(evt -> {
|
logoutMenuItem.addActionListener(evt -> Platform.runLater(UserUtil::logout));
|
||||||
hide();
|
|
||||||
Platform.runLater(UserUtil::logout);
|
|
||||||
});
|
|
||||||
popup.add(logoutMenuItem);
|
popup.add(logoutMenuItem);
|
||||||
|
|
||||||
// Adding the status change items
|
// Adding the status change items
|
||||||
@ -76,12 +97,17 @@ public final class StatusTrayIcon implements EventListener {
|
|||||||
}
|
}
|
||||||
popup.add(statusSubMenu);
|
popup.add(statusSubMenu);
|
||||||
|
|
||||||
trayIcon.setPopupMenu(popup);
|
// Initialize the icon
|
||||||
|
trayIcon = new TrayIcon(createImage(), "Envoy", popup);
|
||||||
|
|
||||||
// Only display messages if the stage is not focused and the current user status
|
// Only display messages if the stage is not focused and the current user status
|
||||||
// is not BUSY (if BUSY, displayMessages will be false)
|
// is not BUSY (if BUSY, displayMessageNotification will be false)
|
||||||
stage.focusedProperty().addListener((ov, wasFocused, isFocused) -> displayMessages =
|
stage.focusedProperty()
|
||||||
!displayMessages && wasFocused ? false : !isFocused);
|
.addListener((ov, wasFocused, isFocused) -> displayMessageNotification =
|
||||||
|
!displayMessageNotification && wasFocused ? false : !isFocused);
|
||||||
|
|
||||||
|
// Listen to changes in the total unread message amount
|
||||||
|
Chat.getTotalUnreadAmount().addListener((ov, oldValue, newValue) -> updateImage());
|
||||||
|
|
||||||
// Show the window if the user clicks on the icon
|
// Show the window if the user clicks on the icon
|
||||||
trayIcon.addActionListener(evt -> Platform.runLater(() -> {
|
trayIcon.addActionListener(evt -> Platform.runLater(() -> {
|
||||||
@ -102,7 +128,7 @@ public final class StatusTrayIcon implements EventListener {
|
|||||||
public void show() {
|
public void show() {
|
||||||
try {
|
try {
|
||||||
SystemTray.getSystemTray().add(trayIcon);
|
SystemTray.getSystemTray().add(trayIcon);
|
||||||
} catch (final AWTException e) {}
|
} catch (AWTException e) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -110,22 +136,89 @@ public final class StatusTrayIcon implements EventListener {
|
|||||||
*
|
*
|
||||||
* @since Envoy Client v0.2-beta
|
* @since Envoy Client v0.2-beta
|
||||||
*/
|
*/
|
||||||
|
@Event(eventType = Logout.class)
|
||||||
public void hide() {
|
public void hide() {
|
||||||
SystemTray.getSystemTray().remove(trayIcon);
|
SystemTray.getSystemTray().remove(trayIcon);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Event
|
@Event
|
||||||
private void onOwnStatusChange(OwnStatusChange statusChange) {
|
private void onOwnStatusChange(OwnStatusChange statusChange) {
|
||||||
displayMessages = !statusChange.get().equals(UserStatus.BUSY);
|
displayMessageNotification = !statusChange.get().equals(UserStatus.BUSY);
|
||||||
|
trayIcon.getImage().flush();
|
||||||
|
trayIcon.setImage(createImage());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Event
|
@Event
|
||||||
private void onMessage(Message message) {
|
private void onMessage(Message message) {
|
||||||
if (displayMessages)
|
if (displayMessageNotification)
|
||||||
trayIcon
|
trayIcon
|
||||||
.displayMessage(message.hasAttachment()
|
.displayMessage(message.hasAttachment()
|
||||||
? "New " + message.getAttachment().getType().toString().toLowerCase()
|
? "New " + message.getAttachment().getType().toString().toLowerCase()
|
||||||
+ " message received"
|
+ " message received"
|
||||||
: "New message received", message.getText(), MessageType.INFO);
|
: "New message received", message.getText(), MessageType.INFO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the tray icon's image by first releasing the resources held by the current image and
|
||||||
|
* then setting a new one generated by the {@link StatusTrayIcon#createImage()} method.
|
||||||
|
*
|
||||||
|
* @since Envoy Client v0.3-beta
|
||||||
|
*/
|
||||||
|
private void updateImage() {
|
||||||
|
trayIcon.getImage().flush();
|
||||||
|
trayIcon.setImage(createImage());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Composes an icon that displays the current user status and the amount of unread messages, if
|
||||||
|
* any are present.
|
||||||
|
*
|
||||||
|
* @since Envoy Client v0.3-beta
|
||||||
|
*/
|
||||||
|
private BufferedImage createImage() {
|
||||||
|
|
||||||
|
// Create a new image with the dimensions of the logo
|
||||||
|
var img = new BufferedImage(size.width, size.height, BufferedImage.TYPE_INT_ARGB);
|
||||||
|
|
||||||
|
// Obtain the draw graphics of the image and copy the logo
|
||||||
|
var g = img.createGraphics();
|
||||||
|
g.drawImage(logo, 0, 0, null);
|
||||||
|
|
||||||
|
// Draw the current user status
|
||||||
|
switch (Context.getInstance().getLocalDB().getUser().getStatus()) {
|
||||||
|
case ONLINE:
|
||||||
|
g.setColor(Color.GREEN);
|
||||||
|
break;
|
||||||
|
case AWAY:
|
||||||
|
g.setColor(Color.ORANGE);
|
||||||
|
break;
|
||||||
|
case BUSY:
|
||||||
|
g.setColor(Color.RED);
|
||||||
|
break;
|
||||||
|
case OFFLINE:
|
||||||
|
g.setColor(Color.GRAY);
|
||||||
|
}
|
||||||
|
g.fillOval(size.width / 2, size.height / 2, size.width / 2, size.height / 2);
|
||||||
|
|
||||||
|
// Draw total amount of unread messages, if any are present
|
||||||
|
if (Chat.getTotalUnreadAmount().get() > 0) {
|
||||||
|
|
||||||
|
// Draw black background circle
|
||||||
|
g.setColor(Color.BLACK);
|
||||||
|
g.fillOval(size.width / 2, 0, size.width / 2, size.height / 2);
|
||||||
|
|
||||||
|
// Unread amount in white
|
||||||
|
String unreadAmount = Chat.getTotalUnreadAmount().get() > 9 ? "9+"
|
||||||
|
: String.valueOf(Chat.getTotalUnreadAmount().get());
|
||||||
|
g.setColor(Color.WHITE);
|
||||||
|
g.setFont(unreadMessageFont);
|
||||||
|
g.drawString(unreadAmount,
|
||||||
|
3 * size.width / 4 - g.getFontMetrics().stringWidth(unreadAmount) / 2,
|
||||||
|
size.height / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finish drawing
|
||||||
|
g.dispose();
|
||||||
|
return img;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,12 +32,12 @@ public final class ChatControl extends HBox {
|
|||||||
setPadding(new Insets(0, 0, 3, 0));
|
setPadding(new Insets(0, 0, 3, 0));
|
||||||
|
|
||||||
// Profile picture
|
// Profile picture
|
||||||
final var contactProfilePic =
|
var contactProfilePic =
|
||||||
new ProfilePicImageView(chat instanceof GroupChat ? groupIcon : userIcon, 32);
|
new ProfilePicImageView(chat instanceof GroupChat ? groupIcon : userIcon, 32);
|
||||||
getChildren().add(contactProfilePic);
|
getChildren().add(contactProfilePic);
|
||||||
|
|
||||||
// Spacing
|
// Spacing
|
||||||
final var leftSpacing = new Region();
|
var leftSpacing = new Region();
|
||||||
leftSpacing.setPrefSize(8, 0);
|
leftSpacing.setPrefSize(8, 0);
|
||||||
leftSpacing.setMinSize(8, 0);
|
leftSpacing.setMinSize(8, 0);
|
||||||
leftSpacing.setMaxSize(8, 0);
|
leftSpacing.setMaxSize(8, 0);
|
||||||
@ -48,17 +48,15 @@ public final class ChatControl extends HBox {
|
|||||||
|
|
||||||
// Unread messages
|
// Unread messages
|
||||||
if (chat.getUnreadAmount() != 0) {
|
if (chat.getUnreadAmount() != 0) {
|
||||||
final var spacing = new Region();
|
var spacing = new Region();
|
||||||
setHgrow(spacing, Priority.ALWAYS);
|
setHgrow(spacing, Priority.ALWAYS);
|
||||||
getChildren().add(spacing);
|
getChildren().add(spacing);
|
||||||
final var unreadMessagesLabel = new Label(Integer.toString(chat.getUnreadAmount()));
|
var unreadMessagesLabel = new Label(
|
||||||
|
chat.getUnreadAmount() > 99 ? "99+" : String.valueOf(chat.getUnreadAmount()));
|
||||||
unreadMessagesLabel.setMinSize(15, 15);
|
unreadMessagesLabel.setMinSize(15, 15);
|
||||||
final var vbox = new VBox();
|
unreadMessagesLabel.setAlignment(Pos.CENTER_RIGHT);
|
||||||
vbox.setAlignment(Pos.CENTER_RIGHT);
|
|
||||||
unreadMessagesLabel.setAlignment(Pos.CENTER);
|
|
||||||
unreadMessagesLabel.getStyleClass().add("unread-messages-amount");
|
unreadMessagesLabel.getStyleClass().add("unread-messages-amount");
|
||||||
vbox.getChildren().add(unreadMessagesLabel);
|
getChildren().add(unreadMessagesLabel);
|
||||||
getChildren().add(vbox);
|
|
||||||
}
|
}
|
||||||
getStyleClass().add("list-element");
|
getStyleClass().add("list-element");
|
||||||
}
|
}
|
||||||
|
@ -107,9 +107,6 @@ public final class ChatScene implements EventListener, Restorable {
|
|||||||
@FXML
|
@FXML
|
||||||
private TextArea contactSearch;
|
private TextArea contactSearch;
|
||||||
|
|
||||||
@FXML
|
|
||||||
private VBox contactOperations;
|
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private TabPane tabPane;
|
private TabPane tabPane;
|
||||||
|
|
||||||
@ -125,9 +122,6 @@ public final class ChatScene implements EventListener, Restorable {
|
|||||||
@FXML
|
@FXML
|
||||||
private HBox ownContactControl;
|
private HBox ownContactControl;
|
||||||
|
|
||||||
@FXML
|
|
||||||
private Region spaceBetweenUserAndSettingsButton;
|
|
||||||
|
|
||||||
private Chat currentChat;
|
private Chat currentChat;
|
||||||
private FilteredList<Chat> chats;
|
private FilteredList<Chat> chats;
|
||||||
private Attachment pendingAttachment;
|
private Attachment pendingAttachment;
|
||||||
@ -175,7 +169,7 @@ public final class ChatScene implements EventListener, Restorable {
|
|||||||
|
|
||||||
// Set the icons of buttons and image views
|
// Set the icons of buttons and image views
|
||||||
settingsButton.setGraphic(
|
settingsButton.setGraphic(
|
||||||
new ImageView(IconUtil.loadIconThemeSensitive("settings", DEFAULT_ICON_SIZE)));
|
new ImageView(IconUtil.loadIconThemeSensitive("settings", 22)));
|
||||||
voiceButton.setGraphic(
|
voiceButton.setGraphic(
|
||||||
new ImageView(IconUtil.loadIconThemeSensitive("microphone", DEFAULT_ICON_SIZE)));
|
new ImageView(IconUtil.loadIconThemeSensitive("microphone", DEFAULT_ICON_SIZE)));
|
||||||
attachmentButton.setGraphic(
|
attachmentButton.setGraphic(
|
||||||
@ -195,7 +189,6 @@ public final class ChatScene implements EventListener, Restorable {
|
|||||||
chatList.setItems(chats = new FilteredList<>(localDB.getChats()));
|
chatList.setItems(chats = new FilteredList<>(localDB.getChats()));
|
||||||
|
|
||||||
// Set the design of the box in the upper-left corner
|
// Set the design of the box in the upper-left corner
|
||||||
settingsButton.setAlignment(Pos.BOTTOM_RIGHT);
|
|
||||||
generateOwnStatusControl();
|
generateOwnStatusControl();
|
||||||
|
|
||||||
Platform.runLater(() -> {
|
Platform.runLater(() -> {
|
||||||
@ -797,15 +790,15 @@ public final class ChatScene implements EventListener, Restorable {
|
|||||||
private void generateOwnStatusControl() {
|
private void generateOwnStatusControl() {
|
||||||
|
|
||||||
// Update the own user status if present
|
// Update the own user status if present
|
||||||
if (ownContactControl.getChildren().get(0) instanceof ContactControl)
|
if (ownContactControl.getChildren().get(1) instanceof ContactControl)
|
||||||
((ContactControl) ownContactControl.getChildren().get(0)).replaceInfoLabel();
|
((ContactControl) ownContactControl.getChildren().get(1)).replaceInfoLabel();
|
||||||
else {
|
else {
|
||||||
|
|
||||||
// Else prepend it to the HBox children
|
// Else prepend it to the HBox children
|
||||||
final var ownUserControl = new ContactControl(localDB.getUser());
|
final var ownUserControl = new ContactControl(localDB.getUser());
|
||||||
ownUserControl.setAlignment(Pos.CENTER_LEFT);
|
ownUserControl.setAlignment(Pos.CENTER_LEFT);
|
||||||
HBox.setHgrow(ownUserControl, Priority.NEVER);
|
HBox.setHgrow(ownUserControl, Priority.NEVER);
|
||||||
ownContactControl.getChildren().add(0, ownUserControl);
|
ownContactControl.getChildren().add(1, ownUserControl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,15 +27,15 @@ public final class GeneralSettingsPane extends SettingsPane {
|
|||||||
final var settingsItems = settings.getItems();
|
final var settingsItems = settings.getItems();
|
||||||
|
|
||||||
// Add hide on close if supported
|
// Add hide on close if supported
|
||||||
if (StatusTrayIcon.isSupported()) {
|
|
||||||
final var hideOnCloseCheckbox =
|
final var hideOnCloseCheckbox =
|
||||||
new SettingsCheckbox((SettingsItem<Boolean>) settingsItems.get("hideOnClose"));
|
new SettingsCheckbox((SettingsItem<Boolean>) settingsItems.get("hideOnClose"));
|
||||||
final var hideOnCloseTooltip = new Tooltip(
|
final var hideOnCloseTooltip = new Tooltip(StatusTrayIcon.isSupported()
|
||||||
"If selected, Envoy will still be present in the task bar when closed.");
|
? "If selected, Envoy will still be present in the task bar when closed."
|
||||||
|
: "status tray icon is not supported on your system.");
|
||||||
hideOnCloseTooltip.setWrapText(true);
|
hideOnCloseTooltip.setWrapText(true);
|
||||||
hideOnCloseCheckbox.setTooltip(hideOnCloseTooltip);
|
hideOnCloseCheckbox.setTooltip(hideOnCloseTooltip);
|
||||||
|
hideOnCloseCheckbox.setDisable(!StatusTrayIcon.isSupported());
|
||||||
getChildren().add(hideOnCloseCheckbox);
|
getChildren().add(hideOnCloseCheckbox);
|
||||||
}
|
|
||||||
|
|
||||||
final var enterToSendCheckbox =
|
final var enterToSendCheckbox =
|
||||||
new SettingsCheckbox((SettingsItem<Boolean>) settingsItems.get("enterToSend"));
|
new SettingsCheckbox((SettingsItem<Boolean>) settingsItems.get("enterToSend"));
|
||||||
|
@ -57,7 +57,7 @@
|
|||||||
<content>
|
<content>
|
||||||
<AnchorPane minHeight="0.0" minWidth="0.0">
|
<AnchorPane minHeight="0.0" minWidth="0.0">
|
||||||
<children>
|
<children>
|
||||||
<VBox fx:id="contactOperations" prefHeight="3000.0"
|
<VBox prefHeight="3000.0"
|
||||||
prefWidth="316.0">
|
prefWidth="316.0">
|
||||||
<children>
|
<children>
|
||||||
<VBox id="search-panel" maxHeight="-Infinity"
|
<VBox id="search-panel" maxHeight="-Infinity"
|
||||||
@ -146,7 +146,8 @@
|
|||||||
<Insets right="1.0" />
|
<Insets right="1.0" />
|
||||||
</GridPane.margin>
|
</GridPane.margin>
|
||||||
</TabPane>
|
</TabPane>
|
||||||
<HBox id="top-bar" alignment="CENTER_LEFT" prefHeight="100.0">
|
<HBox id="top-bar" alignment="CENTER_LEFT" prefHeight="100.0"
|
||||||
|
fx:id="ownContactControl">
|
||||||
<children>
|
<children>
|
||||||
<ImageView id="profile-pic" fx:id="clientProfilePic"
|
<ImageView id="profile-pic" fx:id="clientProfilePic"
|
||||||
fitHeight="43.0" fitWidth="43.0" pickOnBounds="true"
|
fitHeight="43.0" fitWidth="43.0" pickOnBounds="true"
|
||||||
@ -155,23 +156,19 @@
|
|||||||
<Insets left="15.0" top="5.0" right="10.0" />
|
<Insets left="15.0" top="5.0" right="10.0" />
|
||||||
</HBox.margin>
|
</HBox.margin>
|
||||||
</ImageView>
|
</ImageView>
|
||||||
<HBox id="transparent-background" fx:id="ownContactControl">
|
<Region id="transparent-background"
|
||||||
<children>
|
HBox.hgrow="ALWAYS" />
|
||||||
<Region id="transparent-background" prefWidth="120"
|
|
||||||
fx:id="spaceBetweenUserAndSettingsButton" HBox.hgrow="ALWAYS" />
|
|
||||||
<Button fx:id="settingsButton" mnemonicParsing="false"
|
<Button fx:id="settingsButton" mnemonicParsing="false"
|
||||||
onAction="#settingsButtonClicked" prefHeight="30.0"
|
onAction="#settingsButtonClicked" prefHeight="30.0"
|
||||||
prefWidth="30.0" text="" alignment="CENTER">
|
prefWidth="30.0" alignment="CENTER_RIGHT">
|
||||||
<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>
|
||||||
<HBox.margin>
|
<HBox.margin>
|
||||||
<Insets bottom="35.0" left="5.0" top="35.0" />
|
<Insets bottom="35.0" left="5.0" top="35.0" right="10.0"/>
|
||||||
</HBox.margin>
|
</HBox.margin>
|
||||||
</Button>
|
</Button>
|
||||||
</children>
|
</children>
|
||||||
</HBox>
|
|
||||||
</children>
|
|
||||||
<GridPane.margin>
|
<GridPane.margin>
|
||||||
<Insets bottom="1.0" right="1.0" />
|
<Insets bottom="1.0" right="1.0" />
|
||||||
</GridPane.margin>
|
</GridPane.margin>
|
||||||
|
Reference in New Issue
Block a user