diff --git a/pom.xml b/pom.xml
index b6c1c09..52e53b5 100644
--- a/pom.xml
+++ b/pom.xml
@@ -23,7 +23,7 @@
${project.artifactId}
${project.artifactId}
${project.artifactId}
- kst4contest.view.Main
+ kst4contest.view.Kst4ContestApplication
17
3.6.3
${project.artifactId}-${project.version}
diff --git a/src/main/java/kst4contest/ApplicationConstants.java b/src/main/java/kst4contest/ApplicationConstants.java
new file mode 100644
index 0000000..6fcd828
--- /dev/null
+++ b/src/main/java/kst4contest/ApplicationConstants.java
@@ -0,0 +1,8 @@
+package kst4contest;
+
+public class ApplicationConstants {
+ /**
+ * Name of the Application.
+ */
+ public static final String APPLICATION_NAME = "praktiKST";
+}
diff --git a/src/main/java/kst4contest/controller/AppRunner.java b/src/main/java/kst4contest/controller/AppRunner.java
index e10c437..36907e3 100644
--- a/src/main/java/kst4contest/controller/AppRunner.java
+++ b/src/main/java/kst4contest/controller/AppRunner.java
@@ -1,12 +1,12 @@
package kst4contest.controller;
-import kst4contest.view.Main;
+import kst4contest.view.Kst4ContestApplication;
public class AppRunner {
public static void main(String[] args) {
- Main.main(args);
+ Kst4ContestApplication.main(args);
}
diff --git a/src/main/java/kst4contest/controller/DBController.java b/src/main/java/kst4contest/controller/DBController.java
index 799dec6..a348bf6 100644
--- a/src/main/java/kst4contest/controller/DBController.java
+++ b/src/main/java/kst4contest/controller/DBController.java
@@ -8,15 +8,29 @@ import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashMap;
+import kst4contest.ApplicationConstants;
import kst4contest.model.ChatMember;
+import kst4contest.utils.ApplicationFileUtils;
public class DBController {
+ /**
+ * Name of the database file.
+ */
+ public static final String DATABASE_FILE = "praktiKST.db";
+
+ /**
+ * Resource path for the database
+ */
+ public static final String DATABASE_RESOURCE = "/praktiKST.db";
+
private static final DBController dbcontroller = new DBController();
private static Connection connection;
// private static final String DB_PATH = System.getProperty("praktiKST.db");
- private static final String DB_PATH = ("praktiKST.db");
+ private static final String DB_PATH = ApplicationFileUtils.getFilePath(ApplicationConstants.APPLICATION_NAME, DATABASE_FILE);
+
+/*
static {
try {
Class.forName("org.sqlite.JDBC");
@@ -25,6 +39,7 @@ public class DBController {
e.printStackTrace();
}
}
+ */
public DBController() {
initDBConnection();
@@ -48,6 +63,11 @@ public class DBController {
private void initDBConnection() {
try {
+ ApplicationFileUtils.copyResourceIfRequired(
+ ApplicationConstants.APPLICATION_NAME,
+ DATABASE_RESOURCE,
+ DATABASE_FILE
+ );
if (connection != null)
return;
System.out.println("Creating Connection to Database...");
diff --git a/src/main/java/kst4contest/model/ChatPreferences.java b/src/main/java/kst4contest/model/ChatPreferences.java
index 826378e..80fa711 100644
--- a/src/main/java/kst4contest/model/ChatPreferences.java
+++ b/src/main/java/kst4contest/model/ChatPreferences.java
@@ -18,6 +18,8 @@ import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
+import kst4contest.ApplicationConstants;
+import kst4contest.utils.ApplicationFileUtils;
import org.w3c.dom.Comment;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
@@ -34,6 +36,16 @@ import javafx.collections.ObservableList;
public class ChatPreferences {
+ /**
+ * Name of file to store preferences in.
+ */
+ public static final String PREFERENCES_FILE = "preferences.xml";
+
+ /**
+ * Resource with the example properties xml file.
+ */
+ public static final String PREFERENCE_RESOURCE = "/praktiKSTpreferences.xml";
+
/**
* Default constructor will set the default values (also for predefined texts
* and shorts) automatically at initialization
@@ -41,6 +53,7 @@ public class ChatPreferences {
* TODO: delete this from the kst4contest.view/Main.java!
*/
public ChatPreferences() {
+ ApplicationFileUtils.copyResourceIfRequired(ApplicationConstants.APPLICATION_NAME, PREFERENCE_RESOURCE, PREFERENCES_FILE);
// shortcuts[2] = "pse";
// shortcuts[3] = "turn";
@@ -109,7 +122,7 @@ public class ChatPreferences {
String programVersion = "Chat is powered by ON4KST \n\nUsage is free. You are welcome to support: \n\n- my project (donations, bugreports, good ideas are welcome), \n- ON4KST Servers, \n- AirScout developers and \n- OV3T (best AS-data provider of the world). \n\n73 de DO5AMF, Marc (DM5M / DARC X08)";
String logsynch_storeWorkedCallSignsFileNameUDPMessageBackup = "udpReaderBackup.txt";
- String storeAndRestorePreferencesFileName = "praktiKSTpreferences.xml";
+ String storeAndRestorePreferencesFileName = ApplicationFileUtils.getFilePath(ApplicationConstants.APPLICATION_NAME, PREFERENCES_FILE);
String chatState; // working variable only for use by primarystage (title bar)
// ObservableStringValue chatState;
diff --git a/src/main/java/kst4contest/utils/ApplicationFileUtils.java b/src/main/java/kst4contest/utils/ApplicationFileUtils.java
new file mode 100644
index 0000000..3f457cd
--- /dev/null
+++ b/src/main/java/kst4contest/utils/ApplicationFileUtils.java
@@ -0,0 +1,69 @@
+package kst4contest.utils;
+
+import kst4contest.controller.DBController;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Path;
+
+/**
+ * This class has utility methods to handle application files inside the home directory.
+ */
+public class ApplicationFileUtils {
+
+ /**
+ * Gets the path of a file inside the home directory of the user.
+ * @param applicationName Name off the application which is used for the hidden directory
+ * @param fileName Name of the file.
+ * @return The full path inside the user home directory.
+ */
+ public static String getFilePath(final String applicationName, final String fileName) {
+ return Path.of(System.getProperty("user.home"),
+ "." + applicationName,
+ fileName).toString();
+ }
+
+ /**
+ * Copies a resource to the application folder if required.
+ * @param applicationName Name of the application.
+ * @param resourcePath Path of the resource.
+ * @param fileName Name of the target file.
+ */
+ public static void copyResourceIfRequired(final String applicationName, final String resourcePath, final String fileName) {
+ File file = new File(getFilePath(applicationName, fileName));
+
+ if (file.exists()) {
+ return;
+ }
+
+ File parentDir = file.getParentFile();
+ if (!parentDir.exists()) {
+ parentDir.mkdirs();
+ }
+
+ copyResourceToFile(resourcePath, file.getPath());
+ }
+
+ /**
+ * Copies a given resource at a resourcePath to the file path.
+ * @param resourcePath
+ * @param filePath
+ */
+ public static void copyResourceToFile(String resourcePath, String filePath) {
+ try (InputStream resourceStream = ApplicationFileUtils.class.getResourceAsStream(resourcePath);
+ FileOutputStream fileOutputStream = new FileOutputStream(filePath)) {
+
+ if (resourceStream == null) {
+ throw new IllegalArgumentException("Resource not found: " + resourcePath);
+ }
+
+ resourceStream.transferTo(fileOutputStream);
+ } catch (IOException ex) {
+ System.err.println("Exception when copying Application file: " + ex.getMessage());
+ ex.printStackTrace(System.err);
+ }
+ }
+
+}
diff --git a/src/main/java/kst4contest/view/Kst4ContestApplication.java b/src/main/java/kst4contest/view/Kst4ContestApplication.java
new file mode 100644
index 0000000..0abcef9
--- /dev/null
+++ b/src/main/java/kst4contest/view/Kst4ContestApplication.java
@@ -0,0 +1,3220 @@
+package kst4contest.view;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.Optional;
+import java.util.Timer;
+import java.util.TimerTask;
+
+import kst4contest.controller.ChatController;
+import kst4contest.controller.Utils4KST;
+import javafx.application.Application;
+import javafx.application.Platform;
+import javafx.beans.property.SimpleStringProperty;
+import javafx.beans.property.StringProperty;
+import javafx.beans.value.ChangeListener;
+import javafx.beans.value.ObservableValue;
+import javafx.collections.ListChangeListener;
+import javafx.collections.ObservableList;
+import javafx.event.ActionEvent;
+import javafx.event.EventHandler;
+import javafx.geometry.Insets;
+import javafx.geometry.Orientation;
+import javafx.geometry.Pos;
+import javafx.geometry.VPos;
+import javafx.scene.Node;
+import javafx.scene.Scene;
+import javafx.scene.control.Alert;
+import javafx.scene.control.Alert.AlertType;
+import javafx.scene.control.Button;
+import javafx.scene.control.ButtonType;
+import javafx.scene.control.CheckBox;
+import javafx.scene.control.ChoiceBox;
+import javafx.scene.control.ContextMenu;
+import javafx.scene.control.Label;
+import javafx.scene.control.Menu;
+import javafx.scene.control.MenuBar;
+import javafx.scene.control.MenuItem;
+import javafx.scene.control.PasswordField;
+import javafx.scene.control.SelectionMode;
+import javafx.scene.control.Separator;
+import javafx.scene.control.SplitPane;
+import javafx.scene.control.Tab;
+import javafx.scene.control.TabPane;
+import javafx.scene.control.TableCell;
+import javafx.scene.control.TableColumn;
+import javafx.scene.control.TableColumn.CellDataFeatures;
+import javafx.scene.control.TableColumn.CellEditEvent;
+import javafx.scene.control.TableView;
+import javafx.scene.control.TableView.TableViewSelectionModel;
+import javafx.scene.control.TextField;
+import javafx.scene.control.Tooltip;
+import javafx.scene.control.cell.TextFieldTableCell;
+import javafx.scene.input.KeyCode;
+import javafx.scene.input.KeyEvent;
+import javafx.scene.input.MouseButton;
+import javafx.scene.input.MouseEvent;
+import javafx.scene.layout.AnchorPane;
+import javafx.scene.layout.BorderPane;
+import javafx.scene.layout.FlowPane;
+import javafx.scene.layout.GridPane;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.VBox;
+import javafx.scene.paint.Color;
+import javafx.stage.FileChooser;
+import javafx.stage.Stage;
+import javafx.stage.WindowEvent;
+import javafx.util.Callback;
+import kst4contest.model.ChatCategory;
+import kst4contest.model.ChatMember;
+import kst4contest.model.ChatMessage;
+import kst4contest.model.ClusterMessage;
+
+public class Kst4ContestApplication extends Application {
+
+ String chatState;
+ ChatController chatcontroller;
+ Button MYQRGButton; // TODO: clean code? Got the myqrg button out of the factory method to modify
+ // the text later
+ Button MYCALLSetQRGButton;
+
+ Timer timer_buildWindowTitle;
+ Timer timer_chatMemberTableSortTimer; // need that because javafx bug, it´s the only way to actualize the table...
+ Timer timer_updatePrivatemessageTable; // same here
+
+ private TableView initChatMemberTable() {
+
+ TableView tbl_chatMemberTable = new TableView();
+ tbl_chatMemberTable.setTooltip(new Tooltip(
+ "Stations available \n\n Use right click to a station to select predefined texts \n\n Texts can be changed in the config-file"));
+
+ TableColumn callSignCol = new TableColumn("Callsign");
+ callSignCol.setCellValueFactory(new Callback, ObservableValue>() {
+
+ @Override
+ public ObservableValue call(CellDataFeatures cellDataFeatures) {
+ SimpleStringProperty callsgn = new SimpleStringProperty();
+
+ callsgn.setValue(cellDataFeatures.getValue().getCallSign());
+
+ return callsgn;
+ }
+ });
+
+ TableColumn nameCol = new TableColumn("Name");
+ nameCol.setCellValueFactory(new Callback, ObservableValue>() {
+
+ @Override
+ public ObservableValue call(CellDataFeatures cellDataFeatures) {
+ SimpleStringProperty name = new SimpleStringProperty();
+
+ name.setValue(cellDataFeatures.getValue().getName());
+
+ return name;
+ }
+ });
+
+ TableColumn qraCol = new TableColumn("QRA");
+ qraCol.setCellValueFactory(new Callback, ObservableValue>() {
+
+ @Override
+ public ObservableValue call(CellDataFeatures cellDataFeatures) {
+ SimpleStringProperty qra = new SimpleStringProperty();
+
+ qra.setValue(cellDataFeatures.getValue().getQra());
+
+ return qra;
+ }
+ });
+
+ TableColumn qrgCol = new TableColumn("QRG");
+ qrgCol.setCellValueFactory(new Callback, ObservableValue>() {
+
+ @Override
+ public ObservableValue call(CellDataFeatures cellDataFeatures) {
+// StringProperty qrg = new SimpleStringProperty();
+
+// qrg.setValue(cellDataFeatures.getValue().getFrequency());
+// qrg = (cellDataFeatures.getValue().getFrequency());
+
+// if (!qrg.getValue().equals("")) {
+//
+// }
+
+ return cellDataFeatures.getValue().getFrequency();
+ }
+
+ });
+
+ TableColumn airScoutCol = new TableColumn("AP [minutes / pot%]");
+ airScoutCol.setCellValueFactory(new Callback, ObservableValue>() {
+
+ @Override
+ public ObservableValue call(CellDataFeatures cellDataFeatures) {
+ SimpleStringProperty airPlaneInfo = new SimpleStringProperty();
+
+ if (cellDataFeatures.getValue().getAirPlaneReflectInfo().getRisingAirplanes() == null) {
+ airPlaneInfo.setValue(" ");
+ }
+
+ else if (cellDataFeatures.getValue().getAirPlaneReflectInfo().getRisingAirplanes().size() <= 0) {
+ airPlaneInfo.setValue(" ");
+ } else {
+ String apInfoText = ""
+ + cellDataFeatures.getValue().getAirPlaneReflectInfo().getRisingAirplanes().get(0)
+ .getArrivingDurationMinutes()
+ + " (" + cellDataFeatures.getValue().getAirPlaneReflectInfo().getRisingAirplanes().get(0)
+ .getPotential()
+ + "%)";
+//
+//
+ if (cellDataFeatures.getValue().getAirPlaneReflectInfo().getRisingAirplanes().size() > 1) {
+ apInfoText += " / "
+ + cellDataFeatures.getValue().getAirPlaneReflectInfo().getRisingAirplanes().get(1)
+ .getArrivingDurationMinutes()
+ + " (" + cellDataFeatures.getValue().getAirPlaneReflectInfo().getRisingAirplanes()
+ .get(1).getPotential()
+ + "%)";
+ }
+
+ airPlaneInfo.setValue(apInfoText);
+ }
+
+ return airPlaneInfo;
+ }
+ });
+ /**
+ * HIGH EXPERIMENTAL::::::::
+ */
+ airScoutCol.setCellFactory(new Callback, TableCell>() {
+ public TableCell call(TableColumn param) {
+ return new TableCell() {
+
+ @Override
+ public void updateItem(String item, boolean empty) {
+ super.updateItem(item, empty);
+ if (!isEmpty()) {
+ this.setTextFill(Color.BLACK);
+ // Get fancy and change color based on data
+ if (item.contains("100%")) {
+ this.setTextFill(Color.BLUEVIOLET);
+ } else if (item.contains("75%") && !item.contains("100%")) {
+ this.setTextFill(Color.RED);
+ } else if (item.contains("50%") && ((!item.contains("100%")) || (!item.contains("75%")))) {
+ this.setTextFill(Color.ORANGE);
+ }
+
+ setText(item);
+ }
+ }
+ };
+ }
+ });
+ /**
+ * END HIGH EXPERIMENTAL::::::::
+ */
+
+ TableColumn workedCol = new TableColumn("worked");
+ workedCol.setCellValueFactory(new Callback, ObservableValue>() {
+
+ @Override
+ public ObservableValue call(CellDataFeatures cellDataFeatures) {
+ SimpleStringProperty wkd = new SimpleStringProperty();
+
+ if (cellDataFeatures.getValue().isWorked()) {
+ wkd.setValue("X");
+ } else {
+ wkd.setValue("");
+ }
+
+ return wkd;
+ }
+ });
+
+ TableColumn wkdAny_subcol = new TableColumn("wkd");
+ wkdAny_subcol
+ .setCellValueFactory(new Callback, ObservableValue>() {
+
+ @Override
+ public ObservableValue call(CellDataFeatures cellDataFeatures) {
+ SimpleStringProperty wkd = new SimpleStringProperty();
+
+ if (cellDataFeatures.getValue().isWorked()) {
+ wkd.setValue("X");
+ } else {
+ wkd.setValue("");
+ }
+
+ return wkd;
+ }
+ });
+ wkdAny_subcol.prefWidthProperty().bind(tbl_chatMemberTable.widthProperty().divide(28));
+
+ TableColumn vhfCol_subcol = new TableColumn("144");
+ vhfCol_subcol
+ .setCellValueFactory(new Callback, ObservableValue>() {
+
+ @Override
+ public ObservableValue call(CellDataFeatures cellDataFeatures) {
+ SimpleStringProperty wkd = new SimpleStringProperty();
+
+ if (cellDataFeatures.getValue().isWorked144()) {
+ wkd.setValue("X");
+ } else {
+ wkd.setValue("");
+ }
+
+ return wkd;
+ }
+ });
+ vhfCol_subcol.prefWidthProperty().bind(tbl_chatMemberTable.widthProperty().divide(28));
+
+ TableColumn uhfCol_subcol = new TableColumn("432");
+ uhfCol_subcol
+ .setCellValueFactory(new Callback, ObservableValue>() {
+
+ @Override
+ public ObservableValue call(CellDataFeatures cellDataFeatures) {
+ SimpleStringProperty wkd = new SimpleStringProperty();
+
+ if (cellDataFeatures.getValue().isWorked432()) {
+ wkd.setValue("X");
+ } else {
+ wkd.setValue("");
+ }
+
+ return wkd;
+ }
+ });
+
+ uhfCol_subcol.prefWidthProperty().bind(tbl_chatMemberTable.widthProperty().divide(28));
+
+ TableColumn shf23_subcol = new TableColumn("23");
+ shf23_subcol.setCellValueFactory(new Callback, ObservableValue>() {
+
+ @Override
+ public ObservableValue call(CellDataFeatures cellDataFeatures) {
+ SimpleStringProperty wkd = new SimpleStringProperty();
+
+ if (cellDataFeatures.getValue().isWorked1240()) {
+ wkd.setValue("X");
+ } else {
+ wkd.setValue("");
+ }
+
+ return wkd;
+ }
+ });
+ shf23_subcol.prefWidthProperty().bind(tbl_chatMemberTable.widthProperty().divide(30));
+
+ TableColumn shf13_subcol = new TableColumn("13");
+ shf13_subcol.setCellValueFactory(new Callback, ObservableValue>() {
+
+ @Override
+ public ObservableValue call(CellDataFeatures cellDataFeatures) {
+ SimpleStringProperty wkd = new SimpleStringProperty();
+
+ if (cellDataFeatures.getValue().isWorked2300()) {
+ wkd.setValue("X");
+ } else {
+ wkd.setValue("");
+ }
+
+ return wkd;
+ }
+ });
+ shf13_subcol.prefWidthProperty().bind(tbl_chatMemberTable.widthProperty().divide(30));
+
+ TableColumn shf9_subcol = new TableColumn("9");
+ shf9_subcol.setCellValueFactory(new Callback, ObservableValue>() {
+
+ @Override
+ public ObservableValue call(CellDataFeatures cellDataFeatures) {
+ SimpleStringProperty wkd = new SimpleStringProperty();
+
+ if (cellDataFeatures.getValue().isWorked3400()) {
+ wkd.setValue("X");
+ } else {
+ wkd.setValue("");
+ }
+
+ return wkd;
+ }
+ });
+ shf9_subcol.prefWidthProperty().bind(tbl_chatMemberTable.widthProperty().divide(32));
+
+ TableColumn shf6_subcol = new TableColumn("6");
+ shf6_subcol.setCellValueFactory(new Callback, ObservableValue>() {
+
+ @Override
+ public ObservableValue call(CellDataFeatures cellDataFeatures) {
+ SimpleStringProperty wkd = new SimpleStringProperty();
+
+ if (cellDataFeatures.getValue().isWorked5600()) {
+ wkd.setValue("X");
+ } else {
+ wkd.setValue("");
+ }
+
+ return wkd;
+ }
+ });
+ shf6_subcol.prefWidthProperty().bind(tbl_chatMemberTable.widthProperty().divide(32));
+
+ TableColumn shf3_subcol = new TableColumn("3");
+ shf3_subcol.setCellValueFactory(new Callback, ObservableValue>() {
+
+ @Override
+ public ObservableValue call(CellDataFeatures cellDataFeatures) {
+ SimpleStringProperty wkd = new SimpleStringProperty();
+
+ if (cellDataFeatures.getValue().isWorked10G()) {
+ wkd.setValue("X");
+ } else {
+ wkd.setValue("");
+ }
+
+ return wkd;
+ }
+ });
+
+ shf3_subcol.prefWidthProperty().bind(tbl_chatMemberTable.widthProperty().divide(32));
+
+// TableColumn uhfCol_subcol = new TableColumn("432"); //TODO: Worked band analysis
+// TableColumn shf23_subcol = new TableColumn("23");
+// TableColumn shf13_subcol = new TableColumn("13");
+// TableColumn shf9_subcol = new TableColumn("9");
+// TableColumn shf6_subcol = new TableColumn("6");
+// TableColumn shf3_subcol = new TableColumn("3");
+ workedCol.getColumns().addAll(wkdAny_subcol, vhfCol_subcol, uhfCol_subcol, shf23_subcol, shf13_subcol,
+ shf9_subcol, shf6_subcol, shf3_subcol); // TODO: automatize enabling to users bandChoice
+
+ tbl_chatMemberTable.getColumns().addAll(callSignCol, nameCol, qraCol, qrgCol, airScoutCol, workedCol);
+
+ tbl_chatMemberTable.setItems(chatcontroller.getLst_chatMemberList());
+
+// chatcontroller.getLst_chatMemberList().addListener(new ListChangeListener() {
+//// ObservableStringValue chatState = new SimpleStringProperty();
+//
+// @Override
+// public void onChanged(javafx.collections.ListChangeListener.Change extends ChatMember> pChange) {
+//// while (pChange.next()) {
+//// System.out.println("List changed");
+//
+// //TODO: Das kann man ggf anders machen
+//
+// String chatState = chatcontroller.getChatPreferences().getProgramVersion() + " / "
+// + "Connected to: " + chatcontroller.getChatPreferences().getLoginChatCategory() + " / "
+// + chatcontroller.getLst_chatMemberList().size() + " users online.";
+// chatcontroller.getChatPreferences().setChatState(chatState);
+//
+//// chatcontroller.getChatPreferences().setChatState(chatcontroller.getChatPreferences().getProgramVersion() + " / "
+//// + "Connected to: " + chatcontroller.getChatPreferences().getLoginChatCategory() + " / "
+//// + chatcontroller.getLst_chatMemberList().size() + " users online.");
+//// primaryStage.setTitle("asdf");
+//// primaryStage.setTitle(chatcontroller.getChatPreferences().getProgramVersion() + " / "
+//// + "Connected to: " + chatcontroller.getChatPreferences().getLoginChatCategory() + " / "
+//// + chatcontroller.getLst_chatMemberList().size() + " users online.");
+//// }
+// }
+// });
+
+ tbl_chatMemberTable.getSortOrder().add(callSignCol);
+
+ /**
+ * timer_chatMemberTableSortTimer -->
+ * This part fixes a javafx bug. The update of the Chatmember fields is (for any
+ * reason) not visible in the ui. Its neccessarry to sort the table in intervals
+ * to keep the table up to date. Otherwise
+ */
+
+ timer_chatMemberTableSortTimer = new Timer();
+
+ timer_chatMemberTableSortTimer.scheduleAtFixedRate(new TimerTask() {
+
+ public void run() {
+ Thread.currentThread().setName("chatMemberTableSortTimer");
+
+ Platform.runLater(() -> {
+
+ try {
+
+// tbl_chatMemberTable.sort();
+
+ } catch (Exception e) {
+ System.out.println("[Main.java, Warning:] Table sorting (actualizing) failed this time.");
+ }
+
+ tbl_chatMemberTable.refresh();
+
+ });
+ }
+ }, new Date(), 3000);
+
+ tbl_chatMemberTable.setColumnResizePolicy(TableView.UNCONSTRAINED_RESIZE_POLICY);
+ tbl_chatMemberTable.autosize();
+
+ return tbl_chatMemberTable;
+ }
+
+ /**
+ * Initializes the right click contextmenu for the chatmember-table, sets the
+ * clickhandler for the contextmenu out of a string array (each menuitam will be
+ * created out of exact one array-entry). These are initialized by the
+ * chatpreferences object out of the config-xml
+ *
+ * @param menuTexts
+ * @return
+ */
+// private ContextMenu initChatMemberTableContextMenu(String[] menuTexts) { old mechanic
+//
+// ContextMenu chatMemberContextMenu = new ContextMenu();
+//
+// for (int i = 0; i < menuTexts.length; i++) {
+// final MenuItem menuItem = new MenuItem(menuTexts[i]);
+// menuItem.setOnAction(new EventHandler() {
+// public void handle(ActionEvent event) {
+// txt_chatMessageUserInput.setText(txt_chatMessageUserInput.getText() + menuItem.getText());
+// }
+// });
+//
+// chatMemberContextMenu.getItems().add(menuItem);
+// }
+//
+//// MenuItem macro1 = new MenuItem("Pse Sked?");
+//// macro1.setOnAction(new EventHandler() {
+//// public void handle(ActionEvent event) {
+//// txt_chatMessageUserInput.setText(txt_chatMessageUserInput.getText() + macro1.getText());
+//// }
+//// });
+//// MenuItem macro10 = new MenuItem("Pse qrg 2m?");
+//// MenuItem macro20 = new MenuItem("Pse Call at ");
+//// MenuItem macro30 = new MenuItem("In qso nw, pse qrx, I will meep you");
+//// MenuItem macro40 = new MenuItem("Pse qrg 70cm?");
+//// MenuItem macro50 = new MenuItem("pse qrg 23cm?");
+//// MenuItem macro60 = new MenuItem("____________________________________");
+//// MenuItem macro70 = new MenuItem("Watch QSO history");
+////
+//// chatMemberContextMenu.getItems().add(macro1);
+//// chatMemberContextMenu.getItems().add(macro10);
+//// chatMemberContextMenu.getItems().add(macro20);
+//// chatMemberContextMenu.getItems().add(macro30);
+//// chatMemberContextMenu.getItems().add(macro40);
+//// chatMemberContextMenu.getItems().add(macro50);
+//// chatMemberContextMenu.getItems().add(macro60);
+//// chatMemberContextMenu.getItems().add(macro70);
+//
+// return chatMemberContextMenu;
+//
+// }
+
+ /**
+ * Initializes the right click contextmenu for the chatmember-table, sets the
+ * clickhandler for the contextmenu out of a string array (each menuitam will be
+ * created out of exact one array-entry). These are initialized by the
+ * chatpreferences object out of the config-xml
+ *
+ * @param menuTexts
+ * @return
+ */
+ private ContextMenu initChatMemberTableContextMenu(ObservableList contextMenuEntries) { // new mechanic
+
+ ContextMenu chatMemberContextMenu = new ContextMenu();
+
+ for (Iterator iterator = contextMenuEntries.iterator(); iterator.hasNext();) {
+ String string = (String) iterator.next();
+ final MenuItem menuItem = new MenuItem(string);
+ menuItem.setOnAction(new EventHandler() {
+ public void handle(ActionEvent event) {
+ txt_chatMessageUserInput.setText(txt_chatMessageUserInput.getText() + menuItem.getText());
+ }
+ });
+
+ chatMemberContextMenu.getItems().add(menuItem);
+
+ }
+
+// MenuItem macro1 = new MenuItem("Pse Sked?");
+// macro1.setOnAction(new EventHandler() {
+// public void handle(ActionEvent event) {
+// txt_chatMessageUserInput.setText(txt_chatMessageUserInput.getText() + macro1.getText());
+// }
+// });
+// MenuItem macro10 = new MenuItem("Pse qrg 2m?");
+// MenuItem macro20 = new MenuItem("Pse Call at ");
+// MenuItem macro30 = new MenuItem("In qso nw, pse qrx, I will meep you");
+// MenuItem macro40 = new MenuItem("Pse qrg 70cm?");
+// MenuItem macro50 = new MenuItem("pse qrg 23cm?");
+// MenuItem macro60 = new MenuItem("____________________________________");
+// MenuItem macro70 = new MenuItem("Watch QSO history");
+//
+// chatMemberContextMenu.getItems().add(macro1);
+// chatMemberContextMenu.getItems().add(macro10);
+// chatMemberContextMenu.getItems().add(macro20);
+// chatMemberContextMenu.getItems().add(macro30);
+// chatMemberContextMenu.getItems().add(macro40);
+// chatMemberContextMenu.getItems().add(macro50);
+// chatMemberContextMenu.getItems().add(macro60);
+// chatMemberContextMenu.getItems().add(macro70);
+
+ return chatMemberContextMenu;
+
+ }
+
+ /**
+ * initializes the tableview in which the cq- and beacon-texts are shown
+ *
+ * @return
+ */
+ private TableView initChatGeneralMSGTable() {
+
+ TableView tbl_generalMSGTable = new TableView();
+ tbl_generalMSGTable.setTooltip(new Tooltip("General messages are shown here (handle it like CQ messages)"));
+
+ TableColumn timeCol = new TableColumn("Time");
+ timeCol.setCellValueFactory(new Callback, ObservableValue>() {
+
+ @Override
+ public ObservableValue call(CellDataFeatures cellDataFeatures) {
+ SimpleStringProperty time = new SimpleStringProperty();
+
+ time.setValue(new Utils4KST()
+ .time_convertEpochToReadable(cellDataFeatures.getValue().getMessageGeneratedTime()));
+
+ return time;
+ }
+ });
+
+ TableColumn callSignCol = new TableColumn("Callsign");
+ callSignCol.setCellValueFactory(new Callback, ObservableValue>() {
+
+ @Override
+ public ObservableValue call(CellDataFeatures cellDataFeatures) {
+ SimpleStringProperty callSign = new SimpleStringProperty();
+
+ if (cellDataFeatures.getValue().getSender() != null) {
+
+ callSign.setValue(cellDataFeatures.getValue().getSender().getCallSign());
+ } else {
+
+ callSign.setValue("");// TODO: Prevents a bug of not setting all values as a default
+ }
+ return callSign;
+ }
+ });
+
+ TableColumn nameCol = new TableColumn("Name");
+ nameCol.setCellValueFactory(new Callback, ObservableValue>() {
+
+ @Override
+ public ObservableValue call(CellDataFeatures cellDataFeatures) {
+ SimpleStringProperty name = new SimpleStringProperty();
+
+ if (cellDataFeatures.getValue().getSender() != null) {
+
+ name.setValue(cellDataFeatures.getValue().getSender().getName());
+ } else {
+
+ name.setValue("");// TODO: Prevents a bug of not setting all values as a default
+ }
+ return name;
+ }
+ });
+
+ TableColumn qrgCol = new TableColumn("Last QRG");
+ qrgCol.setCellValueFactory(new Callback, ObservableValue>() {
+
+ @Override
+ public ObservableValue call(CellDataFeatures cellDataFeatures) {
+ StringProperty qrg = new SimpleStringProperty();
+
+ if (cellDataFeatures.getValue().getSender() != null) {
+
+// qrg.setValue(cellDataFeatures.getValue().getSender().getFrequency());
+ qrg = cellDataFeatures.getValue().getSender().getFrequency();
+ } else {
+
+ qrg.setValue("");// TODO: Prevents a bug of not setting all values as a default
+ }
+ return qrg;
+ }
+ });
+
+ TableColumn msgCol = new TableColumn("Message");
+ msgCol.setCellValueFactory(new Callback, ObservableValue>() {
+
+ @Override
+ public ObservableValue call(CellDataFeatures cellDataFeatures) {
+ SimpleStringProperty msg = new SimpleStringProperty();
+
+ if (cellDataFeatures.getValue().getMessageText() != null) {
+
+ msg.setValue(cellDataFeatures.getValue().getMessageText());
+ } else {
+
+ msg.setValue("");// TODO: Prevents a bug of not setting all values as a default
+ }
+ return msg;
+ }
+ });
+ msgCol.prefWidthProperty().bind(tbl_generalMSGTable.widthProperty().divide(2));
+
+ msgCol.setCellFactory(new Callback, TableCell>() {
+ public TableCell call(TableColumn param) {
+ return new TableCell() {
+
+ @Override
+ public void updateItem(String item, boolean empty) {
+ super.updateItem(item, empty);
+ if (!isEmpty()) {
+ this.setTextFill(Color.BLACK);
+ // Get fancy and change color based on data
+ if (item.toUpperCase()
+ .contains(chatcontroller.getChatPreferences().getLoginCallSign().toUpperCase())) {
+ this.setTextFill(Color.GREEN);
+ }
+ setText(item);
+ }
+ }
+ };
+ }
+ });
+
+ tbl_generalMSGTable.getColumns().addAll(timeCol, callSignCol, nameCol, msgCol, qrgCol);
+
+ ObservableList generalMSGList = chatcontroller.getLst_toAllMessageList();
+ tbl_generalMSGTable.setItems(generalMSGList);
+
+ return tbl_generalMSGTable;
+ }
+
+ private TableView initChatprivateMSGTable() {
+
+ TableView tbl_privateMSGTable = new TableView();
+ tbl_privateMSGTable.setTooltip(new Tooltip("Private messages to you are shown here"));
+
+ TableColumn timeCol = new TableColumn("Time");
+ timeCol.setCellValueFactory(new Callback, ObservableValue>() {
+
+ @Override
+ public ObservableValue call(CellDataFeatures cellDataFeatures) {
+ SimpleStringProperty time = new SimpleStringProperty();
+
+ time.setValue(new Utils4KST()
+ .time_convertEpochToReadable(cellDataFeatures.getValue().getMessageGeneratedTime()));
+
+ return time;
+ }
+ });
+
+ TableColumn callSignCol = new TableColumn("Callsign");
+ callSignCol.setCellValueFactory(new Callback, ObservableValue>() {
+
+ @Override
+ public ObservableValue call(CellDataFeatures cellDataFeatures) {
+ SimpleStringProperty callSign = new SimpleStringProperty();
+
+ if (cellDataFeatures.getValue().getSender() != null) {
+
+ callSign.setValue(cellDataFeatures.getValue().getSender().getCallSign());
+ } else {
+
+ callSign.setValue("");// TODO: Prevents a bug of not setting all values as a default
+ }
+ return callSign;
+ }
+ });
+
+ callSignCol.setCellFactory(new Callback, TableCell>() {
+ public TableCell call(TableColumn param) {
+ return new TableCell() {
+
+ @Override
+ public void updateItem(String item, boolean empty) {
+ super.updateItem(item, empty);
+ if (!isEmpty()) {
+ this.setTextFill(Color.BLACK);
+ // Get fancy and change color based on data
+ if (item.contains(chatcontroller.getChatPreferences().getLoginCallSign())) {
+ this.setTextFill(Color.GREEN);
+
+// AudioClip sound = new AudioClip(getClass().getResource("/K.mp3").toExternalForm());
+// sound.play();
+
+ }
+ setText(item);
+ }
+ }
+ };
+ }
+ });
+
+ TableColumn nameCol = new TableColumn("Name");
+ nameCol.setCellValueFactory(new Callback, ObservableValue>() {
+
+ @Override
+ public ObservableValue call(CellDataFeatures cellDataFeatures) {
+ SimpleStringProperty name = new SimpleStringProperty();
+
+ if (cellDataFeatures.getValue().getSender() != null) {
+
+ name.setValue(cellDataFeatures.getValue().getSender().getName());
+ } else {
+
+ name.setValue("");// TODO: Prevents a bug of not setting all values as a default
+ }
+ return name;
+ }
+ });
+
+ TableColumn qraCol = new TableColumn("QRA");
+ qraCol.setCellValueFactory(new Callback, ObservableValue>() {
+
+ @Override
+ public ObservableValue call(CellDataFeatures cellDataFeatures) {
+ SimpleStringProperty qra = new SimpleStringProperty();
+
+ if (cellDataFeatures.getValue().getSender() != null) {
+
+ qra.setValue(cellDataFeatures.getValue().getSender().getQra());
+ } else {
+
+ qra.setValue("");// TODO: Prevents a bug of not setting all values as a default
+ }
+ return qra;
+ }
+ });
+
+ TableColumn qrgCol = new TableColumn("Last known QRG");
+ qrgCol.setCellValueFactory(new Callback, ObservableValue>() {
+
+ @Override
+ public ObservableValue call(CellDataFeatures cellDataFeatures) {
+ StringProperty qrg = new SimpleStringProperty();
+
+ if (cellDataFeatures.getValue().getSender() != null) {
+
+// qrg.setValue(cellDataFeatures.getValue().getSender().getFrequency());
+ qrg = cellDataFeatures.getValue().getSender().getFrequency();
+ } else {
+
+ qrg.setValue("");// TODO: Prevents a bug of not setting all values as a default
+ }
+ return qrg;
+ }
+ });
+
+ TableColumn msgCol = new TableColumn("Message");
+ msgCol.setCellValueFactory(new Callback, ObservableValue>() {
+
+ @Override
+ public ObservableValue call(CellDataFeatures cellDataFeatures) {
+ SimpleStringProperty msg = new SimpleStringProperty();
+
+ if (cellDataFeatures.getValue().getMessageText() != null) {
+
+ msg.setValue(cellDataFeatures.getValue().getMessageText());
+ } else {
+
+ msg.setValue("");// TODO: Prevents a bug of not setting all values as a default
+ }
+ return msg;
+ }
+ });
+ msgCol.prefWidthProperty().bind(tbl_privateMSGTable.widthProperty().divide(2.5));
+
+ TableColumn airScoutCol = new TableColumn("AP [minutes / pot%]");
+ airScoutCol.setCellValueFactory(new Callback, ObservableValue>() {
+
+ boolean isnull =false;
+
+ @Override
+ public ObservableValue call(CellDataFeatures cellDataFeatures) {
+ SimpleStringProperty airPlaneInfo = new SimpleStringProperty();
+
+ try {
+ cellDataFeatures.getValue().getSender().getAirPlaneReflectInfo().getRisingAirplanes();
+ } catch (NullPointerException e) {
+ airPlaneInfo.setValue(" ");
+ isnull = true;
+ }
+
+// if (cellDataFeatures.getValue().getSender().getAirPlaneReflectInfo().getRisingAirplanes() == null) {
+// airPlaneInfo.setValue(" ");
+// }
+
+// else
+ try {
+ if (cellDataFeatures.getValue().getSender().getAirPlaneReflectInfo().getRisingAirplanes()
+ .size() <= 0) {
+ airPlaneInfo.setValue(" ");}
+
+ } catch (NullPointerException e) {
+ airPlaneInfo.setValue(" ");
+ isnull = true;
+ }
+// if (cellDataFeatures.getValue().getSender().getAirPlaneReflectInfo().getRisingAirplanes()
+// .size() <= 0) {
+// airPlaneInfo.setValue(" ");
+// }
+
+// else
+ if (!isnull) {
+ String apInfoText = ""
+ + cellDataFeatures.getValue().getSender().getAirPlaneReflectInfo().getRisingAirplanes()
+ .get(0).getArrivingDurationMinutes()
+ + " (" + cellDataFeatures.getValue().getSender().getAirPlaneReflectInfo()
+ .getRisingAirplanes().get(0).getPotential()
+ + "%)";
+//
+//
+ if (cellDataFeatures.getValue().getSender().getAirPlaneReflectInfo().getRisingAirplanes()
+ .size() > 1) {
+ apInfoText += " / "
+ + cellDataFeatures.getValue().getSender().getAirPlaneReflectInfo().getRisingAirplanes()
+ .get(1).getArrivingDurationMinutes()
+ + " (" + cellDataFeatures.getValue().getSender().getAirPlaneReflectInfo()
+ .getRisingAirplanes().get(1).getPotential()
+ + "%)";
+ }
+
+ airPlaneInfo.setValue(apInfoText);
+ } else {
+ airPlaneInfo.setValue(" "); //no planes rising
+ }
+
+ return airPlaneInfo;
+ }
+ });
+ /**
+ * HIGH EXPERIMENTAL::::::::
+ */
+ airScoutCol.setCellFactory(new Callback, TableCell>() {
+ public TableCell call(TableColumn param) {
+ return new TableCell() {
+
+ @Override
+ public void updateItem(String item, boolean empty) {
+ super.updateItem(item, empty);
+ if (!isEmpty()) {
+ this.setTextFill(Color.BLACK);
+ // Get fancy and change color based on data
+ if (item.contains("100%")) {
+ this.setTextFill(Color.BLUEVIOLET);
+ } else if (item.contains("75%") && !item.contains("100%")) {
+ this.setTextFill(Color.RED);
+ } else if (item.contains("50%") && ((!item.contains("100%")) || (!item.contains("75%")))) {
+ this.setTextFill(Color.ORANGE);
+ }
+
+ setText(item);
+ }
+ }
+ };
+ }
+ });
+ /**
+ * END HIGH EXPERIMENTAL::::::::
+ */
+
+ tbl_privateMSGTable.getColumns().addAll(timeCol, callSignCol, nameCol, qraCol, msgCol, qrgCol, airScoutCol);
+
+ ObservableList privateMSGList = chatcontroller.getLst_toMeMessageList();
+ tbl_privateMSGTable.setItems(privateMSGList);
+
+ return tbl_privateMSGTable;
+ }
+
+ private TableView initDXClusterTable() {
+
+ TableView tbl_DXCTable = new TableView();
+ tbl_DXCTable.setTooltip(new Tooltip("Cluster Messages are shown here"));
+
+ TableColumn timeCol = new TableColumn("Time");
+ timeCol.setCellValueFactory(new Callback, ObservableValue>() {
+
+ @Override
+ public ObservableValue call(CellDataFeatures cellDataFeatures) {
+ SimpleStringProperty time = new SimpleStringProperty();
+
+ time.setValue(
+ new Utils4KST().time_convertEpochToReadable(cellDataFeatures.getValue().getTimeGenerated()));
+
+ return time;
+ }
+ });
+
+ TableColumn callSignCol = new TableColumn("Call tx");
+ callSignCol
+ .setCellValueFactory(new Callback, ObservableValue>() {
+
+ @Override
+ public ObservableValue call(CellDataFeatures cellDataFeatures) {
+ SimpleStringProperty callSign = new SimpleStringProperty();
+
+ if (cellDataFeatures.getValue().getSender() != null) {
+
+ callSign.setValue(cellDataFeatures.getValue().getSender().getCallSign());
+ } else {
+
+ callSign.setValue("");// TODO: Prevents a bug of not setting all values as a default
+ }
+ return callSign;
+ }
+ });
+
+ TableColumn locTXCol = new TableColumn("LOC tx");
+ locTXCol.setCellValueFactory(new Callback, ObservableValue>() {
+
+ @Override
+ public ObservableValue call(CellDataFeatures cellDataFeatures) {
+ SimpleStringProperty locTX = new SimpleStringProperty();
+
+ if (cellDataFeatures.getValue().getSender() != null) {
+
+ locTX.setValue(cellDataFeatures.getValue().getSender().getQra());
+ } else {
+
+ locTX.setValue("");// TODO: Prevents a bug of not setting all values as a default
+ }
+ return locTX;
+ }
+ });
+
+ TableColumn callSignRXCol = new TableColumn("Call rx");
+ callSignRXCol
+ .setCellValueFactory(new Callback, ObservableValue>() {
+
+ @Override
+ public ObservableValue call(CellDataFeatures cellDataFeatures) {
+ SimpleStringProperty callSignRX = new SimpleStringProperty();
+
+ if (cellDataFeatures.getValue().getReceiver() != null) {
+
+ callSignRX.setValue(cellDataFeatures.getValue().getReceiver().getCallSign());
+ } else {
+
+ callSignRX.setValue("");// TODO: Prevents a bug of not setting all values as a default
+ }
+ return callSignRX;
+ }
+ });
+
+ TableColumn locRXCol = new TableColumn("LOC rx");
+ locRXCol.setCellValueFactory(new Callback, ObservableValue>() {
+
+ @Override
+ public ObservableValue call(CellDataFeatures cellDataFeatures) {
+ SimpleStringProperty locRX = new SimpleStringProperty();
+
+ if (cellDataFeatures.getValue().getSender() != null) {
+
+ locRX.setValue(cellDataFeatures.getValue().getReceiver().getQra());
+ } else {
+
+ locRX.setValue("");// TODO: Prevents a bug of not setting all values as a default
+ }
+ return locRX;
+ }
+ });
+
+ TableColumn qrgCol = new TableColumn("QRG");
+ qrgCol.setCellValueFactory(new Callback, ObservableValue>() {
+
+ @Override
+ public ObservableValue call(CellDataFeatures cellDataFeatures) {
+ StringProperty qrg = new SimpleStringProperty();
+
+ if (cellDataFeatures.getValue().getReceiver() != null) {
+
+// qrg.setValue(cellDataFeatures.getValue().getReceiver().getFrequency());
+ qrg = cellDataFeatures.getValue().getReceiver().getFrequency();
+ } else {
+
+ qrg.setValue("");// TODO: Prevents a bug of not setting all values as a default
+ }
+ return qrg;
+ }
+ });
+
+ TableColumn msgCol = new TableColumn("Message");
+ msgCol.setCellValueFactory(new Callback, ObservableValue>() {
+
+ @Override
+ public ObservableValue call(CellDataFeatures cellDataFeatures) {
+ SimpleStringProperty msg = new SimpleStringProperty();
+
+ if (cellDataFeatures.getValue().getMessageInhibited() != null) {
+
+ msg.setValue(cellDataFeatures.getValue().getMessageInhibited());
+ } else {
+
+ msg.setValue("");// TODO: Prevents a bug of not setting all values as a default
+ }
+ return msg;
+ }
+ });
+
+ TableColumn workedCol = new TableColumn("wkd");
+ workedCol
+ .setCellValueFactory(new Callback, ObservableValue>() {
+
+ @Override
+ public ObservableValue call(CellDataFeatures cellDataFeatures) {
+ SimpleStringProperty wkd = new SimpleStringProperty();
+
+ wkd.setValue(cellDataFeatures.getValue().isReceiverWkd() + "");
+
+ if (cellDataFeatures.getValue().isReceiverWkd()) {
+ wkd.setValue("X");
+ } else {
+ wkd.setValue("");
+ }
+
+ return wkd;
+ }
+ });
+
+ tbl_DXCTable.getColumns().addAll(timeCol, callSignCol, locTXCol, callSignRXCol, locRXCol, qrgCol, msgCol,
+ workedCol);
+
+ ObservableList clusterMSGList = chatcontroller.getLst_clusterMemberList();
+ tbl_DXCTable.setItems(clusterMSGList);
+
+ return tbl_DXCTable;
+ }
+
+ private TableView initChatToOtherMSGTable() {
+
+ TableView tbl_toOtherMSGTable = new TableView();
+ tbl_toOtherMSGTable.setTooltip(new Tooltip("Messages between other member are shown here"));
+
+ TableColumn timeCol = new TableColumn("Time");
+ timeCol.setCellValueFactory(new Callback, ObservableValue>() {
+
+ @Override
+ public ObservableValue call(CellDataFeatures cellDataFeatures) {
+ SimpleStringProperty time = new SimpleStringProperty();
+
+ time.setValue(new Utils4KST()
+ .time_convertEpochToReadable(cellDataFeatures.getValue().getMessageGeneratedTime()));
+
+ return time;
+ }
+ });
+
+ TableColumn callSignTRCVCol = new TableColumn("Call TX");
+ callSignTRCVCol
+ .setCellValueFactory(new Callback, ObservableValue>() {
+
+ @Override
+ public ObservableValue call(CellDataFeatures cellDataFeatures) {
+ SimpleStringProperty callSign = new SimpleStringProperty();
+
+ if (cellDataFeatures.getValue().getSender() != null) {
+
+ callSign.setValue(cellDataFeatures.getValue().getSender().getCallSign());
+ } else {
+
+ callSign.setValue("");// TODO: Prevents a bug of not setting all values as a default
+ }
+ return callSign;
+ }
+ });
+
+ TableColumn callSignRCVRCol = new TableColumn("Call RX");
+ callSignRCVRCol
+ .setCellValueFactory(new Callback, ObservableValue