Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion src/main/java/com/codedead/opal/OpalApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,11 @@ public static void main(final String[] args) {
* Method that is called by the JavaFX runtime
*
* @param primaryStage The initial Stage object
* @throws IOException When the {@link java.awt.TrayIcon} could not be created
*/
@Override
public void start(final Stage primaryStage) {
public void start(final Stage primaryStage) throws IOException {
Platform.setImplicitExit(false);
final SettingsController settingsController;

try {
Expand Down Expand Up @@ -121,5 +123,11 @@ public void start(final Stage primaryStage) {

logger.info("Showing the MainWindow");
primaryStage.show();

// Load tray icons after displaying the main stage to display the proper icon in the task bar / activities bar (linux)
mainWindowController.createTrayIcon();
if (Boolean.parseBoolean(properties.getProperty("trayIcon", "false"))) {
mainWindowController.showTrayIcon();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,6 @@ public void setSettingsController(final SettingsController settingsController) {
translationBundle = ResourceBundle.getBundle("translations.OpalApplication", locale);
}

/**
* Method that is invoked to initialize the FXML object
*/
@FXML
private void initialize() {
logger.info("Initializing AboutWindow");
}

/**
* Method that is called when the close button is selected
*/
Expand Down
101 changes: 99 additions & 2 deletions src/main/java/com/codedead/opal/controller/MainWindowController.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuItem;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.DragEvent;
Expand All @@ -25,11 +27,15 @@
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
import java.util.List;

import static com.codedead.opal.utils.SharedVariables.DEFAULT_LOCALE;

Expand Down Expand Up @@ -66,6 +72,7 @@ public final class MainWindowController implements IAudioTimer {
@FXML
private MenuItem mniOpenSoundPreset;

private TrayIcon trayIcon;
private SettingsController settingsController;
private UpdateController updateController;
private ResourceBundle translationBundle;
Expand Down Expand Up @@ -267,8 +274,6 @@ public void run() {
*/
@FXML
private void initialize() {
logger.info("Initializing MainWindow");

mniOpenSoundPreset.setGraphic(new ImageView(new Image(Objects.requireNonNull(getClass().getResourceAsStream("/images/open.png")))));
mniSaveSoundPreset.setGraphic(new ImageView(new Image(Objects.requireNonNull(getClass().getResourceAsStream("/images/save.png")))));
mniReset.setGraphic(new ImageView(new Image(Objects.requireNonNull(getClass().getResourceAsStream("/images/refresh.png")))));
Expand All @@ -295,6 +300,98 @@ private void initialize() {
});
}

/**
* Create a tray icon
*
* @throws IOException When the {@link TrayIcon} could not be created
*/
public void createTrayIcon() throws IOException {
if (!SystemTray.isSupported()) {
logger.warn("SystemTray is not supported");
return;
}

final SystemTray tray = SystemTray.getSystemTray();
final Dimension trayIconSize = tray.getTrayIconSize();
final PopupMenu popup = new PopupMenu();
final BufferedImage trayIconImage = ImageIO.read(Objects.requireNonNull(getClass().getResource("/images/opal.png")));
final TrayIcon localTrayIcon = new TrayIcon(trayIconImage.getScaledInstance(trayIconSize.width, trayIconSize.height, java.awt.Image.SCALE_SMOOTH));
final java.awt.MenuItem displayItem = new java.awt.MenuItem(translationBundle.getString("Display"));
final java.awt.MenuItem settingsItem = new java.awt.MenuItem(translationBundle.getString("Settings"));
final java.awt.MenuItem aboutItem = new java.awt.MenuItem(translationBundle.getString("About"));
final java.awt.MenuItem exitItem = new java.awt.MenuItem(translationBundle.getString("Exit"));

// Platform.runLater to run on the JavaFX thread
displayItem.addActionListener(e -> Platform.runLater(this::hideShowStage));
settingsItem.addActionListener(e -> Platform.runLater(this::settingsAction));
aboutItem.addActionListener(e -> Platform.runLater(this::aboutAction));
exitItem.addActionListener(e -> Platform.runLater(this::exitAction));

popup.add(displayItem);
popup.addSeparator();
popup.add(settingsItem);
popup.add(aboutItem);
popup.addSeparator();
popup.add(exitItem);

localTrayIcon.setToolTip("Opal");
localTrayIcon.setPopupMenu(popup);
localTrayIcon.addMouseListener(new java.awt.event.MouseAdapter() {
@Override
public void mouseClicked(final java.awt.event.MouseEvent evt) {
if (evt.getClickCount() == 2) {
Platform.runLater(() -> hideShowStage());
}
}
});

this.trayIcon = localTrayIcon;
}

/**
* Display the tray icon
*/
public void showTrayIcon() {
if (trayIcon == null) {
logger.warn("TrayIcon cannot be null!");
return;
}

final SystemTray tray = SystemTray.getSystemTray();
try {
if (!Arrays.asList(tray.getTrayIcons()).contains(trayIcon)) {
tray.add(trayIcon);
}
} catch (final AWTException e) {
logger.error("TrayIcon could not be added", e);
}
}

/**
* Hide the tray icon
*/
public void hideTrayIcon() {
if (trayIcon == null) {
logger.warn("TrayIcon cannot be null!");
return;
}

final SystemTray tray = SystemTray.getSystemTray();
tray.remove(trayIcon);
}

/**
* Hide the current stage
*/
private void hideShowStage() {
final Stage stage = (Stage) grpControls.getScene().getWindow();
if (stage.isShowing()) {
stage.hide();
} else {
stage.show();
}
}

/**
* Open a sound preset
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@

public final class SettingsWindowController {

@FXML
private CheckBox chbTrayIcon;
@FXML
private ComboBox<String> cboTheme;
@FXML
Expand Down Expand Up @@ -63,14 +65,6 @@ public SettingsWindowController() {
logger.info("Initializing new SettingsWindowController object");
}

/**
* Method that is invoked to initialize the FXML object
*/
@FXML
private void initialize() {
logger.info("Initializing SettingsWindow");
}

/**
* Set the {@link SettingsController} object
*
Expand Down Expand Up @@ -165,6 +159,7 @@ private void loadSettings() {
chbAutoUpdate.setSelected(Boolean.parseBoolean(settingsController.getProperties().getProperty("autoUpdate", "true")));
chbMediaButtons.setSelected(Boolean.parseBoolean(settingsController.getProperties().getProperty("mediaButtons", "true")));
chbDragDrop.setSelected(Boolean.parseBoolean(settingsController.getProperties().getProperty("dragDrop", "true")));
chbTrayIcon.setSelected(Boolean.parseBoolean(settingsController.getProperties().getProperty("trayIcon", "false")));
chbTimerApplicationShutdown.setSelected(Boolean.parseBoolean(settingsController.getProperties().getProperty("timerApplicationShutdown", "false")));
cboDelayType.getSelectionModel().select(delayType);
cboTheme.getSelectionModel().select(themeIndex);
Expand All @@ -185,6 +180,7 @@ private void resetSettingsAction() {
settingsController.createDefaultProperties();
settingsController.setProperties(settingsController.readPropertiesFile());
mainWindowController.loadMediaButtonVisibility(Boolean.parseBoolean(settingsController.getProperties().getProperty("mediaButtons", "true")));
mainWindowController.hideTrayIcon();

loadSettings();
} catch (final IOException ex) {
Expand All @@ -204,7 +200,14 @@ private void saveSettingsAction() {
settingsController.getProperties().setProperty("autoUpdate", Boolean.toString(chbAutoUpdate.isSelected()));
settingsController.getProperties().setProperty("mediaButtons", Boolean.toString(chbMediaButtons.isSelected()));
settingsController.getProperties().setProperty("dragDrop", Boolean.toString(chbDragDrop.isSelected()));
settingsController.getProperties().setProperty("trayIcon", Boolean.toString(chbTrayIcon.isSelected()));

mainWindowController.loadMediaButtonVisibility(chbMediaButtons.isSelected());
if (chbTrayIcon.isSelected()) {
mainWindowController.showTrayIcon();
} else {
mainWindowController.hideTrayIcon();
}

showAlertIfLanguageMismatch(settingsController.getProperties().getProperty("locale", DEFAULT_LOCALE));

Expand Down
1 change: 1 addition & 0 deletions src/main/resources/default.properties
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ timerApplicationShutdown=false
mediaButtons=true
dragDrop=true
theme=light
trayIcon=false
2 changes: 2 additions & 0 deletions src/main/resources/translations/OpalApplication.properties
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,5 @@ NordDark=Nord dark
Space=Space
Restaurant=Restaurant
Cancel=Cancel
Display=Display
TrayIcon=Tray icon
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,5 @@ NordDark=Norden dunkel
Space=Weltraum
Restaurant=Restaurant
Cancel=Abbrechen
Display=Anzeige
TrayIcon=Benachrichtigungssymbol
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,5 @@ NordDark=Nord dark
Space=Space
Restaurant=Restaurant
Cancel=Cancel
Display=Display
TrayIcon=Tray icon
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,5 @@ NordDark=Nord oscuro
Space=Espacio
Restaurant=Restaurante
Cancel=Cancelar
Display=Monitor
TrayIcon=Icono de bandeja
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,5 @@ NordDark=Nord foncé
Space=L'espace
Restaurant=Restaurant
Cancel=Annuler
Display=Affichage
TrayIcon=Icône de la barre
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ Phone=Telefoon
Rain=Regen
Reset=Reset
ResetSettingsError=Kan de instellingen niet resetten!
RestartRequired=Gelieve de applicatie te herstarten om te taal te wijzigen.
RestartRequired=Gelieve de applicatie te herstarten om te taal te wijzigen!
Save=Opslaan
SaveSettingsError=Kan instellingen niet opslaan!
SaveSoundPreset=Sla geluidsinstellingen op
Expand Down Expand Up @@ -84,3 +84,5 @@ NordDark=Nord donker
Space=De ruimte
Restaurant=Restaurant
Cancel=Annuleren
Display=Weergave
TrayIcon=Ladepictogram
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,5 @@ NordDark=Норд темный
Space=Космос
Restaurant=Ресторан
Cancel=Отмена
Display=Отображать
TrayIcon=Значок в трее
23 changes: 16 additions & 7 deletions src/main/resources/windows/SettingsWindow.fxml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
<RowConstraints/>
<RowConstraints/>
<RowConstraints/>
<RowConstraints/>
</rowConstraints>

<columnConstraints>
Expand All @@ -68,12 +69,18 @@
<Insets bottom="3" left="3" right="3" top="3"/>
</GridPane.margin>
</CheckBox>
<Label GridPane.rowIndex="3" GridPane.columnIndex="0" text="%Language">
<CheckBox fx:id="chbTrayIcon" GridPane.columnSpan="2" GridPane.rowIndex="3"
GridPane.columnIndex="0" text="%TrayIcon">
<GridPane.margin>
<Insets bottom="3" left="3" right="3" top="3"/>
</GridPane.margin>
</CheckBox>
<Label GridPane.rowIndex="4" GridPane.columnIndex="0" text="%Language">
<GridPane.margin>
<Insets bottom="3" left="3" right="3" top="3"/>
</GridPane.margin>
</Label>
<ComboBox fx:id="cboLanguage" GridPane.rowIndex="3" GridPane.columnIndex="1" maxWidth="Infinity">
<ComboBox fx:id="cboLanguage" GridPane.rowIndex="4" GridPane.columnIndex="1" maxWidth="Infinity">
<GridPane.margin>
<Insets bottom="3" left="3" right="3" top="3"/>
</GridPane.margin>
Expand All @@ -89,23 +96,23 @@
</items>
</ComboBox>

<Label GridPane.rowIndex="4" GridPane.columnIndex="0" text="%Theme">
<Label GridPane.rowIndex="5" GridPane.columnIndex="0" text="%Theme">
<GridPane.margin>
<Insets bottom="3" left="3" right="3" top="3"/>
</GridPane.margin>
</Label>
<ComboBox fx:id="cboTheme" GridPane.rowIndex="4" GridPane.columnIndex="1" maxWidth="Infinity">
<ComboBox fx:id="cboTheme" GridPane.rowIndex="5" GridPane.columnIndex="1" maxWidth="Infinity">
<GridPane.margin>
<Insets bottom="3" left="3" right="3" top="3"/>
</GridPane.margin>
</ComboBox>

<Label GridPane.rowIndex="5" GridPane.columnIndex="0" text="%LogLevel">
<Label GridPane.rowIndex="6" GridPane.columnIndex="0" text="%LogLevel">
<GridPane.margin>
<Insets bottom="3" left="3" right="3" top="3"/>
</GridPane.margin>
</Label>
<ComboBox fx:id="cboLogLevel" GridPane.rowIndex="5" GridPane.columnIndex="1" maxWidth="Infinity">
<ComboBox fx:id="cboLogLevel" GridPane.rowIndex="6" GridPane.columnIndex="1" maxWidth="Infinity">
<GridPane.margin>
<Insets bottom="3" left="3" right="3" top="3"/>
</GridPane.margin>
Expand Down Expand Up @@ -176,18 +183,20 @@
<ColumnConstraints/>
</columnConstraints>

<!--suppress JavaFxUnresolvedStyleClassReference -->
<Button GridPane.columnIndex="0" minWidth="100" text="%Reset"
onAction="#resetSettingsAction" styleClass="danger">
<GridPane.margin>
<Insets bottom="5" left="5" right="5" top="5"/>
</GridPane.margin>
</Button>
<Button GridPane.columnIndex="1" GridPane.halignment="RIGHT" minWidth="100" text="%Cancel"
onAction="#cancelAction">
onAction="#cancelAction" cancelButton="true">
<GridPane.margin>
<Insets bottom="5" right="5" top="5"/>
</GridPane.margin>
</Button>
<!--suppress JavaFxUnresolvedStyleClassReference -->
<Button GridPane.columnIndex="2" GridPane.halignment="RIGHT" minWidth="100" text="%Save"
onAction="#saveSettingsAction" styleClass="success">
<GridPane.margin>
Expand Down