Deep learning bug fixes ()

* Updates to deep leanring and TD display

Better error dialogs for deep learning module
Stopped data plots being added to a tab pane when there is only one data block add to a graph.

* Updates to time display and bug fixes in deep learning classifier.
This commit is contained in:
Jamie Mac 2025-02-12 10:37:28 +00:00 committed by GitHub
parent 30dfd34b8a
commit 617b02bd34
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 921 additions and 356 deletions

View File

@ -85,22 +85,37 @@ public class WarnOnce implements PamSettings {
* @param okButtonText the text to use for the OK button instead of OK. If null, the text will stay OK.
* @param cancelButtonText the text to use for the cancel button instead of Cancel. If null, the text will stay Cancel
* otherwise OK_OPTION will always be returned.
* @param disableCheckBioxes - true to disable show once check boxes.
* @return if messageType is OK_CANCEl_OPTION this will return OK_OPTION or CANCEL_OPTION
* otherwise OK_OPTION will always be returned.
*/
public static int showWarning(String title, String message, int messageType, String helpPoint, Throwable error,
String okButtonText, String cancelButtonText) {
String okButtonText, String cancelButtonText, boolean disableCheckBoxes) {
if (PamGUIManager.isSwing()) {
return singleInstance.showWarningDialog(PamController.getMainFrame(),
title, message, messageType, helpPoint, error, okButtonText, cancelButtonText);
title, message, messageType, helpPoint, error, okButtonText, cancelButtonText, disableCheckBoxes);
}
else if (PamGUIManager.isFX()) {
return singleInstance.showWarningDialogFX(null,
title, message, getAlertType(messageType), helpPoint, error, okButtonText, cancelButtonText, false);
title, message, getAlertType(messageType), helpPoint, error, okButtonText, cancelButtonText, disableCheckBoxes);
}
return -1;
}
/**
* Show a warning message in either a Swing or JavaFX dialog. The current GUI type automatically chooses
* the dialog type.
* @param title title of warning.
* @param message warning message (use HTML for multi-line messages).
* @param messageType message type OK_CANCEL_OPTION or WARNING_MESSAGE.
* @return if messageType is OK_CANCEl_OPTION this will return OK_OPTION or CANCEL_OPTION
* otherwise OK_OPTION will always be returned.
*/
public static int showWarning(String title, String message, int messageType, String helpPoint, Throwable error,
String okButtonText, String cancelButtonText) {
return showWarning( title, message, messageType, helpPoint, error, okButtonText, cancelButtonText, false);
}
/**
* Show a warning message in either a Swing or JavaFX dialog. The current GUI type automatically chooses
* the dialog type.
@ -176,7 +191,7 @@ public class WarnOnce implements PamSettings {
* otherwise OK_OPTION will always be returned.
*/
public static int showWarning(Window parent, String title, String message, int messageType) {
return singleInstance.showWarningDialog(parent, title, message, messageType, null, null, null, null);
return singleInstance.showWarningDialog(parent, title, message, messageType, null, null, null, null, false);
}
/**
@ -193,7 +208,7 @@ public class WarnOnce implements PamSettings {
* otherwise OK_OPTION will always be returned.
*/
public static int showNamedWarning(String name, Window parent, String title, String message, int messageType) {
return singleInstance.showWarningDialog(parent, title, message, name, messageType, null, null, null, null);
return singleInstance.showWarningDialog(parent, title, message, name, messageType, null, null, null, null, false);
}
/**
@ -209,7 +224,7 @@ public class WarnOnce implements PamSettings {
* otherwise OK_OPTION will always be returned.
*/
public static int showWarning(Window parent, String title, String message, int messageType, String helpPoint) {
return singleInstance.showWarningDialog(parent, title, message, messageType, helpPoint, null, null, null);
return singleInstance.showWarningDialog(parent, title, message, messageType, helpPoint, null, null, null, false);
}
/**
@ -224,7 +239,7 @@ public class WarnOnce implements PamSettings {
*/
public static int showWarning(Window parent, String title, String message, int messageType, String helpPoint, Throwable error) {
if (canShowDialog()) {
return singleInstance.showWarningDialog(parent, title, message, messageType, helpPoint, error, null, null);
return singleInstance.showWarningDialog(parent, title, message, messageType, helpPoint, error, null, null, false);
} else {
System.out.println(" ");
System.out.println("*** Warning: " + title);
@ -260,7 +275,7 @@ public class WarnOnce implements PamSettings {
* @return if messageType is OK_CANCEL_OPTION this will return OK_OPTION or CANCEL_OPTION, otherwise OK_OPTION will always be returned.
*/
public static int showWarning(Window parent, String title, String message, int messageType, String helpPoint, Throwable error, String okButtonText, String cancelButtonText) {
return singleInstance.showWarningDialog(parent, title, message, messageType, helpPoint, error, okButtonText, cancelButtonText);
return singleInstance.showWarningDialog(parent, title, message, messageType, helpPoint, error, okButtonText, cancelButtonText, false);
}
/**
@ -328,6 +343,7 @@ public class WarnOnce implements PamSettings {
}
}
/**
* Show a warning message in JavaFX dialog.
* @param parent parent frame
@ -343,6 +359,24 @@ public class WarnOnce implements PamSettings {
public static int showWarningFX(javafx.stage.Window parent, String title, String message, AlertType messageType, String helpPoint, Throwable error, String okButtonText, String cancelButtonText) {
return singleInstance.showWarningDialogFX(parent, title, message, messageType, helpPoint, error, okButtonText, cancelButtonText, false);
}
/**
* Show a warning message in JavaFX dialog.
* @param parent parent frame
* @param title title of warning
* @param message warning message
* @param messageType message type AlertType enum
* @param helpPoint Pointer into help file for additional information
* @param error an error that may have caused this dialog to be displayed. Can be null if there was no error
* @param okButtonText the text to use for the ok button instead of OK. If null, the text will stay OK
* @param cancelButtonText the text to use for the cancel button instead of Cancel. If null, the text will stay Cancel
* @param disableCheckBoxes true to disable check boxes.
* @return if messageType is OK_CANCEL_OPTION this will return OK_OPTION or CANCEL_OPTION, otherwise OK_OPTION will always be returned.
*/
public static int showWarningFX(javafx.stage.Window parent, String title, String message, AlertType messageType, String helpPoint, Throwable error, String okButtonText, String cancelButtonText, boolean disableCheckBoxes) {
return singleInstance.showWarningDialogFX(parent, title, message, messageType, helpPoint, error, okButtonText, cancelButtonText, disableCheckBoxes);
}
/**
*
@ -357,8 +391,8 @@ public class WarnOnce implements PamSettings {
* @return if messageType is OK_CANCEN_OPTION this will return OK_OPTION or CANECL_OPTION,
* otherwise OK_OPTION will always be returned.
*/
private int showWarningDialog(Window parent, String title, String message, int messageType, String helpPoint, Throwable error, String okButtonText, String cancelButtonText) {
return showWarningDialog(parent, title, message, title+message, messageType, helpPoint, error, okButtonText, cancelButtonText);
private int showWarningDialog(Window parent, String title, String message, int messageType, String helpPoint, Throwable error, String okButtonText, String cancelButtonText, boolean disableCheckBoxes) {
return showWarningDialog(parent, title, message, title+message, messageType, helpPoint, error, okButtonText, cancelButtonText, disableCheckBoxes);
}
/**
*
@ -374,7 +408,7 @@ public class WarnOnce implements PamSettings {
* @return if messageType is OK_CANCEN_OPTION this will return OK_OPTION or CANECL_OPTION,
* otherwise OK_OPTION will always be returned.
*/
private int showWarningDialog(Window parent, String title, String message, String messageName, int messageType, String helpPoint, Throwable error, String okButtonText, String cancelButtonText) {
private int showWarningDialog(Window parent, String title, String message, String messageName, int messageType, String helpPoint, Throwable error, String okButtonText, String cancelButtonText, boolean disableCheckBoxes) {
// check if we should show the warning again this session
Boolean showAgain = showThisSess.get(messageName);
@ -438,6 +472,7 @@ public class WarnOnce implements PamSettings {
return -1;
}
// show the warning
WarnOnceDialogFX wo = new WarnOnceDialogFX(parent, title, message, messageType, helpPoint, error, okButtonText, cancelButtonText, disableCheckBoxes);
wo.showDialog();
@ -448,4 +483,6 @@ public class WarnOnce implements PamSettings {
}

View File

@ -3,9 +3,15 @@ package PamView.dialog.warn;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Optional;
import PamView.help.PamHelp;
import javafx.geometry.Pos;
import javafx.scene.Group;
import javafx.scene.Node;
@ -16,6 +22,7 @@ import javafx.scene.control.CheckBox;
import javafx.scene.control.DialogPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.stage.Modality;
import javafx.stage.Window;
import pamViewFX.fxNodes.PamHBox;
@ -61,7 +68,11 @@ public class WarnOnceDialogFX {
*/
private CheckBox dontShowAgain;
private HBox checkBoxPane;
private HBox checkBoxPane;
private ButtonType helpButton;
private String helpPoint;
/**
* Constructor the warn once dialog.
@ -73,15 +84,7 @@ public class WarnOnceDialogFX {
* @param error
*/
public WarnOnceDialogFX(Window parentStage, String title, String message, AlertType alertType , String helpPoint, Throwable error) {
this.error=error;
this.message=message;
alert = createAlertWithOptOut(alertType, title, null, message, "Don't show this message again", ButtonType.YES, ButtonType.NO);
// if (alert.showAndWait().filter(t -> t == ButtonType.YES).isPresent()) {
// }
// for now, this is not implemented so just make sure it's not checked. If we want to add it to the dialog, we'll need to rearrange everything
// because the opt-out checkbox is added to the buttons bar in a sneaky way, and you can't do that twice.
dontShowAgainThisSess.setSelected(false);
this(parentStage, title, message, alertType, helpPoint, error, null, null, false);
}
/**
@ -104,22 +107,59 @@ public class WarnOnceDialogFX {
this.error=error;
this.message=message;
ButtonType okButton;
if (oktext==null) okButton = ButtonType.OK;
else okButton = new ButtonType(oktext);
ButtonType cancelButton;
if (canceltext==null) cancelButton = ButtonType.OK;
else cancelButton = new ButtonType(canceltext);
this.helpPoint=helpPoint;
//TODO help point.
ButtonType okButton = ButtonType.OK;
ButtonType cancelButton = ButtonType.CANCEL;
ArrayList<ButtonType> buttons = new ArrayList<ButtonType>();
//figure out what the ok and cancel buttons should be
switch (alertType) {
case CONFIRMATION:
okButton = ButtonType.YES;
cancelButton = ButtonType.NO;
break;
case ERROR:
break;
case INFORMATION:
cancelButton = null;
break;
case NONE:
break;
case WARNING:
cancelButton = new ButtonType("Copy to clipboard");
break;
default:
break;
}
//Override the cancel on OK buttons if set
if (oktext!=null) {
okButton = new ButtonType(oktext);
}
alert = createAlertWithOptOut(alertType, title, null, message, "Don't show this message again", okButton, cancelButton);
if (canceltext!=null) {
cancelButton = new ButtonType(canceltext);
}
//add the buttons
buttons.add(okButton);
if (cancelButton!=null) buttons.add(cancelButton);
//add additional buttons.
if (helpPoint!=null) {
helpButton = new ButtonType("Help...");
buttons.add(helpButton);
}
// System.out.println("Buttons: " + buttons.size());
alert = createAlertWithOptOut(alertType, title, null, message, "Don't show this message again", buttons.toArray(new ButtonType[buttons.size()]));
//System.out.println("CREATE ALERT: " + disableCheckBoxes);
this.disableCheckBoxes(disableCheckBoxes);
dontShowAgainThisSess.setSelected(false);
}
@ -129,10 +169,21 @@ public class WarnOnceDialogFX {
* Show the warning dialog.
*/
public void showDialog() {
if (alert.showAndWait().filter(t -> t == ButtonType.YES).isPresent()) {
//System.out.println("SHOW DIALOG: " +this);
Optional<ButtonType> type = alert.showAndWait();
if (type.filter(t -> t == ButtonType.YES).isPresent()) {
//System.out.println("OK_OPTION: " +this);
answer=WarnOnce.OK_OPTION;
}
else if (type.filter(t -> t == helpButton).isPresent()) {
//System.out.println("HELP: " +this);
answer = WarnOnce.OK_OPTION;
helpButtonPressed();
}
else {
//System.out.println("CANCEL_OPTION: " +this);
answer = WarnOnce.CANCEL_OPTION;
cancelButtonPressed();
}
@ -140,6 +191,34 @@ public class WarnOnceDialogFX {
/**
* If the help button is pressed then we send the user to a help point or a website
*/
private void helpButtonPressed() {
if (check_URL(helpPoint)) {
//go to a websitE
try {
java.awt.Desktop.getDesktop().browse( new URL(helpPoint).toURI());
} catch (IOException | URISyntaxException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
else {
//GO TO pamgUARD HELP,POINT
PamHelp.getInstance().displayContextSensitiveHelp(helpPoint);
}
}
public static boolean check_URL(String str) {
try {
new URL(str).toURI();
return true;
} catch (Exception e) {
return false;
}
}
/**
* If the cancel button is pressed, check if this is a warning message. If it is, then the cancel button is really
@ -184,6 +263,7 @@ public class WarnOnceDialogFX {
ButtonType... buttonTypes) {
Alert alert = new Alert(type);
alert.initModality(Modality.WINDOW_MODAL);
// Need to force the alert to layout in order to grab the graphic,
// as we are replacing the dialog pane with a custom pane
alert.getDialogPane().applyCss();
@ -210,7 +290,10 @@ public class WarnOnceDialogFX {
return checkBoxPane;
}
});
alert.getDialogPane().getButtonTypes().addAll(buttonTypes[0]);
alert.getDialogPane().getButtonTypes().addAll(buttonTypes);
alert.getDialogPane().setContentText(message);
// Fool the dialog into thinking there is some expandable content
// a Group won't take up any space if it has no children
@ -220,6 +303,7 @@ public class WarnOnceDialogFX {
alert.getDialogPane().setGraphic(graphic);
alert.setTitle(title);
alert.setHeaderText(headerText);
return alert;
}

View File

@ -1,15 +1,36 @@
/* General Styling for PAMGuard JavaFX controls which trys to replicate the Swing Flatlaf theme */
/* flatlaf-custom.css - Enhancements for FlatLaf */
/* General Styling */
.root {
-fx-font-family: "Segoe UI", "Tahoma", "Arial", sans-serif;
-fx-font-family: "Segoe UI bold", "Arial", sans-serif; /* Modern font stack */
-fx-font-size: 13px;
-fx-base: #f5f5f5;
-fx-background: #ffffff;
-fx-control-inner-background: #ffffff;
-fx-control-inner-background-alt: #f0f0f0;
-fx-focus-color: #3895EC;
-fx-faint-focus-color: rgba(56, 149, 236, 0.2);
-fx-accent: #3895EC;
-fx-default-button: -fx-accent;
-fx-text-fill: black; /* Set default text color to black */
/* -fx-background-color: #f8f8f8; Let FlatLaf handle the base background */
}
/* Buttons */
.button {
-fx-font-weight: 500;
-fx-background-color: linear-gradient(to bottom, #0078D7, #0069c0); /* Blue gradient */
-fx-text-fill: white;
-fx-padding: 8px 16px;
-fx-border-radius: 4px;
-fx-effect: dropshadow(three-d, rgba(0,0,0,0.1), 4, 0, 0, 2);
-fx-cursor: hand;
}
.button:hover {
-fx-background-color: linear-gradient(to bottom, #0069c0, #005ba3);
}
.button:pressed {
-fx-background-color: linear-gradient(to bottom, #005ba3, #004c85); /* Even darker */
-fx-effect: none; /* Remove shadow on press */
}
.button:disabled {
-fx-opacity: 0.6;
-fx-cursor: default;
}
/* Labels */
@ -17,221 +38,183 @@
-fx-text-fill: #333333;
}
/* Buttons */
.button {
-fx-background-color: #ffffff;
-fx-border-color: #cccccc;
-fx-border-width: 1px;
-fx-padding: 6px 12px;
-fx-text-fill: #333333;
-fx-background-radius: 3px;
-fx-border-radius: 3px;
}
.button:hover {
-fx-background-color: #f0f0f0;
}
.button:pressed {
-fx-background-color: #e6e6e6;
}
.button:default {
-fx-background-color: -fx-accent;
-fx-text-fill: white;
-fx-border-color: transparent;
}
.button:default:hover {
-fx-background-color: #2f7dbe;
}
.button:default:pressed {
-fx-background-color: #266591;
}
/* Text Fields and Text Areas */
.text-field,
.text-area {
-fx-background-color: #ffffff;
-fx-border-color: #cccccc;
-fx-border-width: 1px;
-fx-padding: 4px;
/* Text Fields */
.text-field {
-fx-prompt-text-fill: #999999;
-fx-background-radius: 3px;
-fx-border-radius: 3px;
-fx-border-color: #bbbbbb; /* Lighter border */
-fx-background-color: white; /* Explicit white background, sometimes needed */
-fx-padding: 6px;
-fx-border-radius: 4px;
}
.text-field:focused,
.text-area:focused {
-fx-border-color: -fx-focus-color;
-fx-effect: null;
.text-field:focused {
-fx-border-color: #0078D7; /* Blue border on focus */
-fx-effect: innershadow(three-d, rgba(0,0,0,0.1), 4, 0, 0, 2);
}
/* Checkboxes */
.check-box {
-fx-padding: 2px;
.check-box .box {
-fx-border-color: #aaaaaa;
-fx-background-color: white; /* Needed for some FlatLaf themes */
-fx-border-radius: 2px;
}
.check-box:selected .box {
-fx-background-color: #0078D7;
}
.check-box:focused .box {
-fx-border-color: #0078D7;
}
/* Radio Buttons */
.radio-button .radio {
-fx-border-color: #aaaaaa;
-fx-background-color: white;
-fx-border-radius: 50%;
}
.radio-button:selected .radio {
-fx-background-color: #0078D7;
}
.radio-button:focused .radio {
-fx-border-color: #0078D7;
}
/* Combo Boxes */
.combo-box {
-fx-background-color: #ffffff;
-fx-border-color: #cccccc;
-fx-border-width: 1px;
-fx-padding: 4px;
-fx-background-radius: 3px;
-fx-border-radius: 3px;
}
.combo-box:focused {
-fx-border-color: -fx-focus-color;
-fx-effect: null;
}
/* Toggle Switches (using a custom approach) */
.toggle-switch {
-fx-cursor: hand;
}
.toggle-switch .track {
-fx-background-color: #cccccc;
-fx-background-radius: 10px;
-fx-pref-width: 40px; /* Adjust as needed */
-fx-pref-height: 20px;
}
.toggle-switch:selected .track {
-fx-background-color: -fx-accent;
}
.toggle-switch .thumb {
-fx-border-color: #bbbbbb;
-fx-background-color: white;
-fx-background-radius: 50%;
-fx-pref-width: 16px;
-fx-pref-height: 16px;
-fx-translate-x: -10px; /* Initial position */
-fx-border-radius: 4px;
}
.toggle-switch:selected .thumb {
-fx-translate-x: 10px; /* Shifted position */
}
/****************************************************************
Spinner
****************************************************************/
.spinner {
-fx-background-color: #ffffff;
-fx-border-color: #cccccc;
-fx-border-width: 1px;
-fx-padding: 4px;
-fx-background-radius: 3px;
-fx-border-radius: 3px;
}
.spinner:focused {
-fx-border-color: -fx-focus-color;
-fx-effect: null;
}
.spinner .text-field {
-fx-background-color: inherit; /* Inherit from spinner background */
-fx-border-color: inherit; /* Inherit from spinner border */
-fx-border-width: 0; /* No separate border for the text field */
-fx-padding: 5px 0; /* Consistent vertical padding */
-fx-alignment: center; /* Center text */
}
.spinner .increment-arrow-button,
.spinner .decrement-arrow-button {
-fx-background-color: #d2d2d2; /* Light gray background for buttons */
-fx-border-color: inherit; /* Inherit border from spinner */
-fx-border-width: 0; /* No separate border for buttons */
-fx-padding: 5px 5px;
}
.spinner .increment-arrow-button:hover,
.spinner .decrement-arrow-button:hover {
-fx-background-color: #3895EC; /* FlatLaf blue highlight on hover */
-fx-text-fill: white; /* White arrow on hover */
}
/* Split Arrows (Horizontal) */
.spinner.split-arrows-horizontal {
-fx-border-radius: 3px; /* Ensure rounded corners for the overall spinner */
}
.spinner.split-arrows-horizontal .text-field {
-fx-border-width: 0;
-fx-border-color: inherit;
}
.spinner.split-arrows-horizontal .increment-arrow-button {
-fx-background-radius: 0 3px 3px 0; /* Right rounded corners */
}
.spinner.split-arrows-horizontal .decrement-arrow-button {
-fx-background-radius: 3px 0 0 3px; /* Left rounded corners */
}
/* Fix for borders between elements*/
.spinner.split-arrows-horizontal .increment-arrow-button {
-fx-border-width: 0 1px 0 0;
}
.spinner.split-arrows-horizontal .decrement-arrow-button {
-fx-border-width: 0 0 0 1px;
}
/* Scroll Bars */
.scroll-bar:vertical .increment-button,
.scroll-bar:vertical .decrement-button,
.scroll-bar:horizontal .increment-button,
.scroll-bar:horizontal .decrement-button {
-fx-background-color: transparent;
-fx-border-color: transparent;
}
.scroll-bar:vertical .thumb,
.scroll-bar:horizontal .thumb {
-fx-background-color: rgba(0, 0, 0, 0.2);
-fx-background-radius: 5px;
}
.scroll-bar:vertical .thumb:hover,
.scroll-bar:horizontal .thumb:hover {
-fx-background-color: rgba(0, 0, 0, 0.4);
}
/* Tables */
.table-view {
-fx-background-color: transparent;
-fx-border-color: #cccccc;
-fx-border-width: 1px;
}
.table-view .column-header-background {
-fx-background-color: #f0f0f0;
}
.table-view .column-header {
-fx-border-color: #cccccc;
.combo-box .list-cell {
-fx-padding: 6px;
}
.table-row-cell:even {
-fx-background-color: -fx-control-inner-background;
.combo-box:focused {
-fx-border-color: #0078D7;
}
.table-row-cell:odd {
-fx-background-color: -fx-control-inner-background-alt;
/* List Views */
.list-view {
-fx-border-color: #bbbbbb;
-fx-background-color: white;
-fx-border-radius: 4px;
}
.table-row-cell:selected {
-fx-background-color: rgba(56, 149, 236, 0.3);
.list-view .list-cell {
-fx-padding: 6px;
}
.list-view:focused .list-cell:filled:selected {
-fx-background-color: #0078D7;
-fx-text-fill: white;
}
/* Scroll Bars (Adjust as needed) */
.scroll-bar {
-fx-background-color: #f0f0f0; /* Or transparent if FlatLaf handles it */
}
.scroll-bar .thumb {
-fx-background-color: #bbbbbb;
-fx-border-radius: 4px;
}
/* Hyperlink */
.hyperlink {
-fx-color: #0078D7;
-fx-underline: false;
}
.hyperlink:hover {
-fx-underline: true;
}
/* Titled Pane */
.titled-pane > .title {
-fx-font-weight: bold;
-fx-background-color: #e0e0e0; /* Or let FlatLaf style it */
-fx-padding: 6px;
-fx-border-color: #bbbbbb; /* Subtle border */
-fx-border-width: 0 0 1 0;
}
.titled-pane > .content {
-fx-padding: 10px;
-fx-background-color: white;
}
/* Progress Bar */
.progress-bar {
-fx-background-color: #e0e0e0;
-fx-border-color: #bbbbbb;
-fx-border-width: 1px;
-fx-border-radius: 4px;
}
.progress-bar .bar {
-fx-background-color: #0078D7;
-fx-border-radius: 4px;
}
/* Tab Pane */
.tab-pane .tab-header-area {
/* -fx-background-color: #e0e0e0; Let FlatLaf handle it */
}
.tab-pane .tab {
-fx-background-color: #e0e0e0; /* Or a subtle gradient */
-fx-padding: 8px 16px;
-fx-border-color: #bbbbbb;
-fx-border-width: 1px 1px 0 1px;
-fx-border-radius: 4px 4px 0 0;
}
.tab-pane .tab:selected {
-fx-background-color: white;
-fx-border-color: #bbbbbb;
-fx-border-width: 1px;
}
.tab-pane .tab-content-area {
-fx-padding: 10px;
-fx-background-color: white;
-fx-border-color: #bbbbbb;
-fx-border-width: 0 1px 1px 1px;
}
/* Tool Bar */
.tool-bar {
/* -fx-background-color: #e0e0e0; Let FlatLaf style it */
-fx-padding: 4px;
}
.tool-bar > .button {
-fx-background-color: transparent;
-fx-border-color: transparent;
-fx-text-fill: #333333;
-fx-padding: 4px;
-fx-effect: none;
}
.tool-bar > .button:hover {
-fx-background-color: rgba(0, 120, 215, 0.2); /* Subtle blue highlight */
-fx-border-color: transparent;
}
.tool-bar > .button:pressed {
-fx-background-color: rgba(0, 120, 215, 0.4);
-fx-border-color: transparent;
}
/* ... Add or modify other styles as needed ... */
/* Example: Making the font a bit bolder overall */
.button, .label, .text-field, .check-box, .radio-button, .combo-box, .list-view .list-cell, .tree-view .tree-cell, .hyperlink, .titled-pane > .title, .tab-pane .tab {
-fx-font-weight: 500; /* Adjust as needed */
}

View File

@ -0,0 +1,212 @@
/* Mimic Windows 11 Swing Look in JavaFX */
/* General Styling */
.root {
-fx-font-family: "Segoe UI"; /* Windows 11 default font */
-fx-font-size: 13px; /* Adjust as needed */
}
/* Buttons */
.button {
-fx-background-color: #f0f0f0; /* Light gray background */
-fx-border-color: #cccccc; /* Subtle gray border */
-fx-border-width: 1px;
-fx-border-radius: 3px;
-fx-padding: 6px 12px; /* Adjust padding as needed */
-fx-text-fill: #000000; /* Black text */
-fx-alignment: center; /* Center text */
}
.button:hover {
-fx-background-color: #e0e0e0; /* Slightly darker on hover */
}
.button:pressed {
-fx-background-color: #d0d0d0; /* Even darker when pressed */
}
/* Labels */
.label {
-fx-text-fill: #000000; /* Black text */
}
/* Text Fields */
.text-field {
-fx-background-color: #ffffff; /* White background */
-fx-border-color: #cccccc; /* Gray border */
-fx-border-width: 1px;
-fx-border-radius: 3px;
-fx-padding: 3px;
}
/* Checkboxes */
.check-box .box {
-fx-background-color: #ffffff; /* White box */
-fx-border-color: #cccccc; /* Gray border */
-fx-border-width: 1px;
-fx-border-radius: 2px;
}
.check-box:selected .box {
-fx-background-color: #0078D7; /* Blue checkmark (Windows 11 accent color - adjust if needed) */
}
/* Radio Buttons */
.radio-button .radio {
-fx-background-color: #ffffff; /* White circle */
-fx-border-color: #cccccc; /* Gray border */
-fx-border-width: 1px;
-fx-border-radius: 50%; /* Make it a circle */
}
.radio-button:selected .radio {
-fx-background-color: #0078D7; /* Blue dot (Windows 11 accent color - adjust if needed) */
}
/* Combo Boxes */
.combo-box {
-fx-background-color: #ffffff;
-fx-border-color: #cccccc;
-fx-border-width: 1px;
-fx-border-radius: 3px;
}
.combo-box .list-cell {
-fx-padding: 4px;
}
/* Scroll Bars (Adjust as needed) */
.scroll-bar {
-fx-background-color: #f0f0f0;
}
.scroll-bar .thumb {
-fx-background-color: #cccccc;
-fx-border-radius: 4px;
}
/* Menus and Menu Items */
.menu-bar {
-fx-background-color: #f0f0f0; /* Light gray menu bar */
}
.menu {
-fx-padding: 5px;
}
.menu-item {
-fx-padding: 5px;
}
.menu-item:focused {
-fx-background-color: #e0e0e0; /* Highlight on hover/focus */
}
/* Tooltips */
.tooltip {
-fx-background-color: #ffffff; /* White tooltip background */
-fx-border-color: #cccccc; /* Gray border */
-fx-border-width: 1px;
-fx-padding: 4px;
-fx-text-fill: #000000; /* Black text */
}
/* List View */
.list-view {
-fx-background-color: #ffffff;
-fx-border-color: #cccccc;
-fx-border-width: 1px;
}
.list-view .list-cell {
-fx-padding: 4px;
}
.list-view:focused .list-cell:filled:selected {
-fx-background-color: #0078D7; /* Blue highlight on selection (Windows 11 accent color) */
-fx-text-fill: white;
}
.list-view .list-cell:filled:hover {
-fx-background-color: #e0e0e0; /* Light gray on hover */
}
/* Titled Pane */
.titled-pane > .title {
-fx-background-color: #f0f0f0; /* Light gray title bar */
-fx-padding: 5px;
-fx-border-color: #cccccc;
-fx-border-width: 0 0 1 0; /* Bottom border only */
}
.titled-pane > .content {
-fx-padding: 10px;
}
/* Progress Bar */
.progress-bar {
-fx-background-color: #f0f0f0;
-fx-border-color: #cccccc;
-fx-border-width: 1px;
}
.progress-bar .bar {
-fx-background-color: #0078D7; /* Windows 11 accent color */
}
/* Scroll Pane */
.scroll-pane {
-fx-background-color: #ffffff;
}
/* Tree View */
.tree-view {
-fx-background-color: #ffffff;
}
.tree-view .tree-cell {
-fx-padding: 3px;
}
.tree-view:focused .tree-cell:filled:selected {
-fx-background-color: #0078D7; /* Blue highlight on selection (Windows 11 accent color) */
-fx-text-fill: white;
}
.tree-view .tree-cell:filled:hover {
-fx-background-color: #e0e0e0; /* Light gray on hover */
}
/* Tab Pane */
.tab-pane {
-fx-tab-min-width: 100; /* Adjust minimum tab width as needed */
}
.tab-pane .tab-header-area {
-fx-background-color: #f0f0f0; /* Light gray tab header */
-fx-padding: 0; /* Remove default padding */
}
.tab-pane .tab {
-fx-background-color: #e0e0e0; /* Slightly darker tabs */
-fx-padding: 8px 12px;
-fx-border-color: #cccccc;
-fx-border-width: 1px 1px 0 1px; /* Border on top, left, and right */
-fx-border-radius: 3px 3px 0 0; /* Rounded top corners */
}
.tab-pane .tab:selected {
-fx-background-color: #ffffff; /* White selected tab */
-fx-border-color: #cccccc; /* Border on all sides */
-fx-border-width: 1px;
}
.tab-pane .tab-content-area {
-fx-padding: 10px;
-fx-border-color: #cccccc;
-fx-border-width: 0 1px 1px 1px; /* Border on bottom, left, and right */
}

View File

@ -399,25 +399,45 @@ public abstract class TDDataInfoFX {
//find a number close to the index start,
ListIterator<PamDataUnit> it = getUnitIterator( loopStart, plotNumber);
clearDraw();
clearDraw();
/**
* Need to be careful here. If using line plots then we always want to have the
* first unit outside the screen. This does not matter for scatter points is
* critical for line plots - otherwise the lines do not draw between data units
* outside the screen
*/
if (it.hasPrevious()) {
it.previous();
}
//true to break after painting the next data unit
boolean breakNext = false;
while (it.hasNext()) {
dataUnit = it.next();
count++;
if (dataUnit!=null && shouldDraw(plotNumber, dataUnit)) {
if (dataUnit.getEndTimeInMilliseconds() < loopStart) {
continue;
}
// if (dataUnit.getEndTimeInMilliseconds() < loopStart) {
// continue;
// }
//at some point we have to stop drawing off the end of the screen but again, for line plots
//we want to draw data units that are next if needed. So if past the end of the point that
//needs to be painted, set breakNext to true so the next data unit is painted for line plots
//then exit.
if (dataUnit.getTimeMilliseconds() > loopEnd) {
break;
breakNext = true;
}
drawCalls++;
drawDataUnit(plotNumber, dataUnit, g, scrollStart,
tdProjector ,TDSymbolChooserFX.NORMAL_SYMBOL);
}
if (breakNext) break;
}
// System.out.println("Found: " + drawCalls + " " + this.getDataName() + " to draw");

View File

@ -40,7 +40,7 @@ public abstract class GenericLinePlotInfo extends TDDataInfoFX {
/**
* The last units
*/
private Point2D[][] lastUnits = new Point2D[PamConstants.MAX_CHANNELS][];
private TimePoint2D[][] lastUnits = new TimePoint2D[PamConstants.MAX_CHANNELS][];
public GenericLinePlotInfo(TDDataProviderFX tdDataProvider, TDGraphFX tdGraph, PamDataBlock pamDataBlock) {
@ -54,17 +54,17 @@ public abstract class GenericLinePlotInfo extends TDDataInfoFX {
@Override
public Polygon drawDataUnit(int plotNumber, PamDataUnit pamDataUnit, GraphicsContext g, double scrollStart,
TDProjectorFX tdProjector, int type) {
return drawPredicition(plotNumber, pamDataUnit, g, scrollStart, tdProjector, type);
return drawPredicition(plotNumber, pamDataUnit, g, scrollStart, tdProjector, type);
}
/**
* Get the line data. Each double[] is a separate line with N evenly spaced data points.
* @param pamDataUnit - the pam data unit containing the data.
* @return the line data.
*/
public abstract double[][] getDetData(PamDataUnit pamDataUnit);
/**
* Draw the prediction as a line.
@ -79,49 +79,52 @@ public abstract class GenericLinePlotInfo extends TDDataInfoFX {
*/
public Polygon drawPredicition(int plotNumber, PamDataUnit pamDataUnit, GraphicsContext g, double scrollStart,
TDProjectorFX tdProjector, int type) {
// System.out.println("A Plot line: " + PamCalendar.formatDateTime(pamDataUnit.getTimeMilliseconds()));
// System.out.println("A Plot line: " + PamCalendar.formatDateTime(pamDataUnit.getTimeMilliseconds()));
double mintC= -1000.;
double maxtC = tdProjector.getWidth()+1000.;
if (this.getTDGraph().isWrap()) {
mintC=0;
maxtC=tdProjector.getWidth();
}
int chan = PamUtils.PamUtils.getLowestChannel(pamDataUnit.getChannelBitmap());
g.setLineDashes(null);
double[][] detData = getDetData(pamDataUnit);
// System.out.println("Draw prediction: " + pamDataUnit + " " + detData);
if ((lastUnits[chan]==null || lastUnits[chan].length<1) && detData!=null) {
//System.out.println("lastUnits: " + lastUnits);
//create the array of last units.
lastUnits[chan] = new Point2D[detData.length];
lastUnits[chan] = new TimePoint2D[detData.length];
}
//use the center of the window for plotting
double timeMillis = pamDataUnit.getTimeMilliseconds()+pamDataUnit.getDurationInMilliseconds()/2;
double tC=tdProjector.getTimePix(timeMillis-scrollStart);
//draws lines so tc should be some slop in pixels.
if (tC < mintC || tC>maxtC) {
// System.out.println("Line is outside display " + tC);
return null;
}
// //draws lines so tc should be some slop in pixels.
// if (tC < mintC || tC>maxtC) {
//// System.out.println("Line is outside display " + tC);
// return null;
// }
//
double dataPixel;
Coordinate3d c;
Color color;
double dataBin; //the time between the data points in millis
// System.out.println("A Plot line 2: " + PamCalendar.formatDateTime(pamDataUnit.getTimeMilliseconds()) + " detData " + detData.length);
// System.out.println("A Plot line 2: " + PamCalendar.formatDateTime(pamDataUnit.getTimeMilliseconds()) + " detData " + detData.length);
for (int i=0; i<detData.length; i++) {
@ -130,42 +133,47 @@ public abstract class GenericLinePlotInfo extends TDDataInfoFX {
g.setStroke(color);
g.setFill(color);
for (int j=0; j<detData[i].length; j++) {
if (lastUnits[chan][i]!=null && lastUnits[chan][i].getTimeMillis()>pamDataUnit.getTimeMilliseconds() ) {
//unlikely to ever get here but is a safety stop if the line graph has messed up,
lastUnits[chan][i] = null;
}
dataBin = pamDataUnit.getDurationInMilliseconds()/detData[i].length;
//plot in the middle of the data bin.
timeMillis = (pamDataUnit.getTimeMilliseconds()+dataBin/2);
//brighten the colour up.
//color = Color.color(color.getRed()*0.8, color.getGreen()*0.8, color.getBlue()*0.8);
// System.out.println("TDDataInfoFX: tc: "+tC+ " dataUnitTime: "+PamCalendar.formatTime((long) timeMillis)+" scrollStart: "
// +PamCalendar.formatTime((long) scrollStart)+" (timeMillis-scrollStart)/1000. "+((timeMillis-scrollStart)/1000.));
// System.out.println("TDDataInfoFX: tc: "+tC+ " dataUnitTime: "+PamCalendar.formatTime((long) timeMillis)+" scrollStart: "
// +PamCalendar.formatTime((long) scrollStart)+" (timeMillis-scrollStart)/1000. "+((timeMillis-scrollStart)/1000.));
c = tdProjector.getCoord3d(timeMillis, detData[i][j], 0);
dataPixel = tdProjector.getYPix(detData[i][j]);
if (lastUnits[chan][i]==null) {
lastUnits[chan][i] = new Point2D(tC, dataPixel);
lastUnits[chan][i] = new TimePoint2D(tC, dataPixel, pamDataUnit.getTimeMilliseconds() );
g.fillOval(tC, dataPixel, 10,10);
// System.out.println("Fill oval:");
// System.out.println("Fill oval:");
return null;
}
else {
if (tC>lastUnits[chan][i].getX() && (!this.getTDGraph().isWrap() ||
tC<maxtC && tC>=mintC && lastUnits[chan][i].getX()<maxtC && lastUnits[chan][i].getX()>mintC)) {
//in wrap mode we can get some weird effects with tC co-ordintates. Still have not quite cracked this...
// if (Math.abs(tC - lastUnits[chan][i].getX())>100) {
// System.out.println("tC: " + tC + " lastUnits[i].getX(): " + lastUnits[chan][i].getX()
// + " " + tdProjector. getTimeAxis().getPosition((timeMillis-scrollStart)/1000.) + " " + tdProjector.getWidth());
// }
// if (Math.abs(tC - lastUnits[chan][i].getX())>100) {
// System.out.println("tC: " + tC + " lastUnits[i].getX(): " + lastUnits[chan][i].getX()
// + " " + tdProjector. getTimeAxis().getPosition((timeMillis-scrollStart)/1000.) + " " + tdProjector.getWidth());
// }
g.strokeLine(tC, dataPixel, lastUnits[chan][i].getX(), lastUnits[chan][i].getY());
}
lastUnits[chan][i] = new Point2D(tC, dataPixel);
lastUnits[chan][i] = new TimePoint2D(tC, dataPixel, pamDataUnit.getTimeMilliseconds());
}
tdProjector.addHoverData(new HoverData(c , pamDataUnit, 0, plotNumber));
}
@ -190,8 +198,8 @@ public abstract class GenericLinePlotInfo extends TDDataInfoFX {
}
GeneralProjector p = this.getTDGraph().getGraphProjector();
PamSymbolChooser sc = symbolManager.getSymbolChooser(getTDGraph().getUniqueName(), p);
return new TDManagedSymbolChooserFX(this, sc, TDSymbolChooserFX.DRAW_SYMBOLS);
}
@ -202,33 +210,52 @@ public abstract class GenericLinePlotInfo extends TDDataInfoFX {
* @return the color for that prediciton
*/
public abstract LineInfo getColor(int i);
@Override
public Double getDataValue(PamDataUnit pamDataUnit) {
//this is not used because we have overridden the super drawing class.
return null;
}
public class TimePoint2D extends Point2D {
private long timeMillis;
public TimePoint2D(double x, double y, long timeMillis) {
super(x, y);
this.timeMillis=timeMillis;
}
public long getTimeMillis() {
return timeMillis;
}
public void setTimeMillis(long timeMillis) {
this.timeMillis = timeMillis;
}
}
/**
* Notifications from the PamController are passed to this function.
*
* @param changeType - notification flag.
*/
public void notifyChange(int changeType) {
// System.out.println("Prediction NOTIFYMODELCHANGED: " + changeType);
// System.out.println("Prediction NOTIFYMODELCHANGED: " + changeType);
switch (changeType) {
case PamController.CHANGED_PROCESS_SETTINGS:
lastUnits = new Point2D[PamConstants.MAX_CHANNELS][];
lastUnits = new TimePoint2D[PamConstants.MAX_CHANNELS][];
break;
case PamController.RUN_NORMAL:
lastUnits = new Point2D[PamConstants.MAX_CHANNELS][];
lastUnits = new TimePoint2D[PamConstants.MAX_CHANNELS][];
break;
case PamController.PAM_STOPPING:
lastUnits = new Point2D[PamConstants.MAX_CHANNELS][];
lastUnits = new TimePoint2D[PamConstants.MAX_CHANNELS][];
break;
}
}
}

View File

@ -235,25 +235,28 @@ public class TDDisplayFX extends PamBorderPane {
controlPane=new TDControlPaneFX(tdControl,this);
controlPane.setParams(tdParametersFX);
controlPane.setPrefHeight(CONTROL_PANE_HEIGHT);
controlPane.setStyle("-fx-background-color: -fx-background;");
hidingControlPane=new HidingPane(Side.TOP, controlPane, this, false );
hidingControlPane.showHidePane(tdParametersFX.showControl);
hidingControlPane.getStylesheets().clear();
// hidingControlPane.getStylesheets().clear();
// hidingControlPane.getStylesheets().addAll(PamStylesManagerFX.getPamStylesManagerFX().getCurStyle().getGUICSS()); //style as a settings pane.
hidingControlPane.getHideButton().setStyle("-fx-border-color: none;");
hidingControlPane.getHideButton().setStyle("-fx-border-color: none; -fx-background-radius: 5 5 0 0; -fx-border-radius: 5 5 0 0;");
hidingControlPane.showingProperty().addListener((valProp, oldVal, newVal)->{
//set correct showing property.
tdParametersFX.showControl=newVal;
});
this.setTop(hidingControlPane);
hidingControlPane.showHidePane(true);
//create the button which shows the hiding panel. Although we get this button from the hiding pane, where to place
//it and what colour it is etc has to be set for whatever pane it is to be located in.
showButton=hidingControlPane.getShowButton();
hidingControlPane.setShowButtonOpacity(1.0);
// showButton.getStyleClass().add("transparent-button-square");
showButton.setStyle("-fx-background-radius: 0 0 0 10; -fx-border-color: none;");
showButton.setStyle("-fx-background-radius: 0 0 0 5; -fx-border-color: none;");
showButton.setGraphic(PamGlyphDude.createPamIcon("mdi2c-chevron-down", PamGuiManagerFX.iconSize));
showButton.setPrefWidth(30);
showButton.setMaxHeight(timeAxisSize-20);

View File

@ -55,13 +55,16 @@ import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.geometry.Bounds;
import javafx.geometry.Insets;
import javafx.geometry.Orientation;
import javafx.geometry.Pos;
import javafx.geometry.Side;
import javafx.scene.Cursor;
import javafx.scene.Node;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.MenuItem;
import javafx.scene.control.ScrollPane.ScrollBarPolicy;
import javafx.scene.control.Tooltip;
@ -69,6 +72,7 @@ import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;
import javafx.scene.text.Text;
import javafx.scene.text.TextAlignment;
import javafx.stage.Window;
import javafx.util.Duration;
import pamScrollSystem.coupling.ScrollerCoupling;
@ -156,12 +160,11 @@ public class TDGraphFX extends PamBorderPane {
* Class which holds information on settings for this particular graph.
*/
private TDGraphParametersFX graphParameters;
/**
* The hiding tab pane which contains settings panes for data blocks associated
* with the graph.
* Pane with controls to change TDGraphParameter general settings.
*/
private TDHidingTabPane settingsTabs;
private TDGraphSettingsPane tdSettingsPane;
/**
* Pane which allows users to select which type of data to display on the axis
@ -219,10 +222,18 @@ public class TDGraphFX extends PamBorderPane {
*/
private double[] lastLimitsZoom = null;
/**
* Pane with controls to change TDGraphParameter general settings.
* A scroll pane which holds the settings tabs
*/
private TDGraphSettingsPane tdSettingsPane;
private PamScrollPane dataSettingsScrollPane;
/**
* The hiding tab pane which contains settings panes for data blocks associated
* with the graph.
*/
private TDHidingTabPane dataSettingsTabs;
/**
* Create the graph.
@ -289,7 +300,7 @@ public class TDGraphFX extends PamBorderPane {
* pane contains a tabbed pane which holds settings panes for subscribed data
* block to the graph.
*/
settingsTabs = new TDHidingTabPane(this);
dataSettingsTabs = new TDHidingTabPane(this);
// settingsTabs.setMinHeight(1000);
// settingsTabs.heightProperty().addListener((a,b,c)->{
// System.out.println("Height: " + settingsTabs.getHeight() + " " +
@ -297,17 +308,17 @@ public class TDGraphFX extends PamBorderPane {
// });
// put inside a scroll pane so tht on low dpi displays can still access controls
PamScrollPane scrollPane2 = new PamScrollPane(settingsTabs);
dataSettingsScrollPane = new PamScrollPane(dataSettingsTabs);
// scrollPane2.setFitToWidth(true);
scrollPane2.setFitToHeight(true);
scrollPane2.setHbarPolicy(ScrollBarPolicy.NEVER);
scrollPane2.getStyleClass().clear();
dataSettingsScrollPane.setFitToHeight(true);
dataSettingsScrollPane.setHbarPolicy(ScrollBarPolicy.NEVER);
dataSettingsScrollPane.getStyleClass().clear();
/**
* Create a stack pane to hold everything- means we can add overlay controls and
* buttons Note: icons are set later in setOverlayColour(LIGHT_TD_DISPLAY);
*/
stackPane = new PamHiddenSidePane(null, null, scrollPane, scrollPane2);
stackPane = new PamHiddenSidePane(null, null, scrollPane, dataSettingsScrollPane);
// stackPane.setMinHidePaneHeight(300);
stackPane.getChildren().add(plotPanels);
@ -336,17 +347,18 @@ public class TDGraphFX extends PamBorderPane {
* the hiding-tab-pane we must set the end spacing so the hiding pane does not
* distort when resizing.
*/
settingsTabs.startSpacingProperty().bind(getSettingsPane().getHideButton().widthProperty());
settingsTabs.setHolderPane(getSettingsPane());
dataSettingsTabs.startSpacingProperty().bind(getSettingsPane().getHideButton().widthProperty());
dataSettingsTabs.setHolderPane(getSettingsPane());
// add settings panes if any.
layoutSettingsPanes();
// add plots to center of main pane
this.setCenter(stackPane);
// layout axis.
layoutTDGraph(tdDisplay.getTDParams().orientation);
// add settings panes if any.
layoutSettingsPanes();
// set the default overlay style.
setOverlayColour(LIGHT_TD_DISPLAY);
@ -562,14 +574,52 @@ public class TDGraphFX extends PamBorderPane {
/**
* Sort out the settings pane. The settingsPane contains tabs of the different
* the different settings panes for data blocks associated with this tdGraphFX.
*
* If there are no settings pane then the settings tab pane shows nothing. If there is one settings panes
* then that is used to fill the whole hiding pane. if there is more than one pane then these are added to a tab pane.
*/
private void layoutSettingsPanes() {
// first remove all tabs
settingsTabs.getTabs().removeAll(settingsTabs.getTabs());
dataSettingsTabs.getTabs().removeAll(dataSettingsTabs.getTabs());
//work out how many settings panes there are.
int n=0;
TDSettingsPane settingsPane = null;
for (TDDataInfoFX dataInfo : dataList) {
if (dataInfo.getGraphSettingsPane() == null)
continue;
settingsTabs.addSettingsPane(dataInfo.getGraphSettingsPane());
if (dataInfo.getGraphSettingsPane() != null) {
settingsPane = dataInfo.getGraphSettingsPane();
n++;
}
}
if (n==0) {
dataSettingsScrollPane.setContent(null);
return; //nothing to do.
}
if (n>1) {
//if there are more than two data tabs then we use tabs to layout the data panes
for (TDDataInfoFX dataInfo : dataList) {
if (dataInfo.getGraphSettingsPane() == null)
continue;
dataSettingsTabs.addSettingsPane(dataInfo.getGraphSettingsPane());
}
dataSettingsScrollPane.setContent(dataSettingsTabs);
}
else {
PamBorderPane settingsHolder = new PamBorderPane();
Label label = new Label(settingsPane.getShowingName());
label.setTextAlignment(TextAlignment.CENTER);
PamBorderPane.setAlignment(label, Pos.CENTER);
settingsHolder.setTop(label);
settingsHolder.setCenter(settingsPane.getPane());
settingsHolder.setPadding(new Insets(0,0,0,30));
dataSettingsScrollPane.setContent(settingsHolder);
}
}
@ -1871,8 +1921,8 @@ public class TDGraphFX extends PamBorderPane {
// open the hide pane.
this.getSettingsPane().showHidePane(show);
// expand all the hide tabs.
for (int i = 0; i < this.settingsTabs.getTabs().size(); i++) {
this.settingsTabs.getTabs().get(i).showTab(show);
for (int i = 0; i < this.dataSettingsTabs.getTabs().size(); i++) {
this.dataSettingsTabs.getTabs().get(i).showTab(show);
}
}

View File

@ -48,7 +48,7 @@ public class PamDefaultStyle {
* Relative location of the CSS style sheet to be used for the Pamguard GUI (but
* not dialogs)
*/
protected String guiCSS = "/Resources/css/pamCSS.css";
protected String guiCSS = null;
/**
* Relative location of the CSS style sheet to be used for the Pamguard GUI when
@ -98,6 +98,7 @@ public class PamDefaultStyle {
*/
public ArrayList<String> getGUICSS() {
ArrayList<String> cssStyles = new ArrayList<String>();
if (guiCSS==null) return cssStyles;
if (PamColors.getInstance().getColourScheme().getName() == ColourScheme.NIGHTSCHEME
&& guiCSSNightMode != null) {
cssStyles.add(getClass().getResource(guiCSSNightMode).toExternalForm());
@ -121,6 +122,7 @@ public class PamDefaultStyle {
*/
public ArrayList<String> getDialogCSS() {
ArrayList<String> cssStyles = new ArrayList<String>();
if (dialogCSS==null) return cssStyles;
if (PamColors.getInstance().getColourScheme().getName() == ColourScheme.NIGHTSCHEME
&& dialogCSSNightMode != null) {
cssStyles.add(getClass().getResource(dialogCSSNightMode).toExternalForm());
@ -144,6 +146,7 @@ public class PamDefaultStyle {
*/
public ArrayList<String> getSlidingDialogCSS() {
ArrayList<String> cssStyles = new ArrayList<String>();
if (slidingDialogCSS==null) return cssStyles;
if (PamColors.getInstance().getColourScheme().getName() == ColourScheme.NIGHTSCHEME
&& slidingDialogCSSNightMode != null) {
cssStyles.add(getClass().getResource(slidingDialogCSSNightMode).toExternalForm());

View File

@ -0,0 +1,122 @@
package pamViewFX.fxStyles;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javax.swing.*;
import com.formdev.flatlaf.FlatLightLaf;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class PamFXSwingComparison extends Application {
@Override
public void start(Stage primaryStage) {
try {
UIManager.setLookAndFeel(new FlatLightLaf() );
} catch (UnsupportedLookAndFeelException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// JavaFX Controls
Button fxButton = new Button("JavaFX Button");
Label fxLabel = new Label("JavaFX Label");
TextField fxTextField = new TextField();
CheckBox fxCheckBox = new CheckBox("JavaFX CheckBox");
RadioButton fxRadioButton = new RadioButton("JavaFX RadioButton");
ComboBox<String> fxComboBox = new ComboBox<>();
fxComboBox.getItems().addAll("Item 1", "Item 2", "Item 3");
ListView<String> fxListView = new ListView<>();
fxListView.getItems().addAll("List Item 1", "List Item 2");
// Apply CSS
Scene scene = new Scene(new VBox()); // Placeholder root; we'll set it later
// scene.getStylesheets().add(getClass().getResource("/Resources/css/pamCSS_windows.css").toExternalForm());
scene.getStylesheets().add(getClass().getResource("/Resources/css/pamCSS_flatlaf.css").toExternalForm());
GridPane fxGrid = new GridPane();
fxGrid.setHgap(10);
fxGrid.setVgap(10);
fxGrid.setPadding(new Insets(20));
fxGrid.add(fxButton, 0, 0);
fxGrid.add(fxLabel, 0, 1);
fxGrid.add(fxTextField, 0, 2);
fxGrid.add(fxCheckBox, 0, 3);
fxGrid.add(fxRadioButton, 0, 4);
fxGrid.add(fxComboBox, 0, 5);
fxGrid.add(fxListView, 0, 6);
// Swing Controls
JButton swingButton = new JButton("Swing Button");
JLabel swingLabel = new JLabel("Swing Label");
JTextField swingTextField = new JTextField();
JCheckBox swingCheckBox = new JCheckBox("Swing CheckBox");
JRadioButton swingRadioButton = new JRadioButton("Swing RadioButton");
JComboBox<String> swingComboBox = new JComboBox<>(new String[]{"Item 1", "Item 2", "Item 3"});
JList<String> swingList = new JList<>(new String[]{"List Item 1", "List Item 2"});
JPanel swingPanel = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new java.awt.Insets(10, 10, 10, 10);
gbc.gridx = 0;
gbc.gridy = 0;
swingPanel.add(swingButton, gbc);
gbc.gridy++;
swingPanel.add(swingLabel, gbc);
gbc.gridy++;
swingPanel.add(swingTextField, gbc);
gbc.gridy++;
swingPanel.add(swingCheckBox, gbc);
gbc.gridy++;
swingPanel.add(swingRadioButton, gbc);
gbc.gridy++;
swingPanel.add(swingComboBox, gbc);
gbc.gridy++;
swingPanel.add(new JScrollPane(swingList), gbc); // Add a scroll pane for the JList
// Embed Swing Panel in JavaFX
javafx.embed.swing.SwingNode swingNode = new javafx.embed.swing.SwingNode();
swingNode.setContent(swingPanel);
// Main Layout (Side-by-Side)
VBox root = new VBox();
root.setAlignment(Pos.CENTER);
root.setSpacing(20);
root.setPadding(new Insets(20));
HBox comparisonPane = new HBox();
comparisonPane.setSpacing(20);
comparisonPane.setAlignment(Pos.CENTER);
comparisonPane.getChildren().addAll(fxGrid, swingNode);
root.getChildren().add(comparisonPane);
scene.setRoot(root);
primaryStage.setScene(scene);
primaryStage.setTitle("Swing vs. JavaFX Comparison");
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}

View File

@ -0,0 +1,9 @@
package pamViewFX.fxStyles;
public class PamSwingFXComparisonLauncher {
public static void main(String[] args) {
PamFXSwingComparison.main(args);
}
}

View File

@ -502,7 +502,7 @@ public class DLControl extends PamControlledUnit implements PamSettings {
public void showSettingsDialog(Frame parentFrame) {
if (settingsDialog == null || parentFrame != settingsDialog.getOwner()) {
SettingsPane<RawDLParams> setPane = (SettingsPane<RawDLParams>) getSettingsPane();
setPane.setParams(this.rawDLParmas);
//setPane.setParams(this.rawDLParmas);
settingsDialog = new PamDialogFX2AWT<RawDLParams>(parentFrame, setPane, false);
settingsDialog.setHelpPoint("classifiers.rawDeepLearningHelp.docs.rawDeepLearning");
settingsDialog.setResizable(true);

View File

@ -756,7 +756,7 @@ public class DLClassifyProcess extends PamInstantProcess {
private void addDLAnnotation(PamDataUnit parentDataUnit,
ArrayList<PredictionResult> modelResult) {
System.out.println("DLClassifyProces: Add annnotation to " + parentDataUnit);
//System.out.println("DLClassifyProces: Add annnotation to " + parentDataUnit);
parentDataUnit.addDataAnnotation(new DLAnnotation(dlAnnotationType, modelResult));
//parentDataUnit.updateDataUnit(System.currentTimeMillis());

View File

@ -2,31 +2,21 @@ package rawDeepLearningClassifier.dlClassification.archiveModel;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;
import org.jamdev.jdl4pam.ArchiveModel;
import org.jamdev.jdl4pam.genericmodel.GenericModelParams;
import org.jamdev.jdl4pam.transforms.DLTransform;
import org.jamdev.jdl4pam.transforms.DLTransformsFactory;
import org.jamdev.jdl4pam.transforms.FreqTransform;
import org.jamdev.jdl4pam.transforms.jsonfile.DLTransformParser2;
import org.jamdev.jdl4pam.transforms.jsonfile.DLTransformsParser;
import org.json.JSONObject;
import PamUtils.PamArrayUtils;
import PamView.dialog.warn.WarnOnce;
import ai.djl.MalformedModelException;
import ai.djl.engine.EngineException;
import rawDeepLearningClassifier.DLControl;
import rawDeepLearningClassifier.DLStatus;
import rawDeepLearningClassifier.dlClassification.animalSpot.StandardModelParams;
import rawDeepLearningClassifier.dlClassification.genericModel.DLModelWorker;
import rawDeepLearningClassifier.dlClassification.genericModel.GenericModelWorker;
import rawDeepLearningClassifier.dlClassification.genericModel.StandardPrediction;
@ -90,8 +80,7 @@ public class ArchiveModelWorker extends GenericModelWorker {
//System.out.println(Paths.get(genericParams.modelPath));
this.currentPath = dlParams.modelPath;
dlModel = loadModel(currentPath);
//System.out.println("LOAD A NEW MODEL: ");
//System.out.println(genericModel.getModel().getModelPath().getFileName());
System.out.println("LOAD A NEW MODEL: " + currentPath);
}
}
catch (EngineException e) {

View File

@ -3,32 +3,51 @@ package rawDeepLearningClassifier.layoutFX;
import java.util.ArrayList;
import PamView.dialog.warn.WarnOnce;
import PamView.dialog.warn.WarnOnceDialogFX;
import javafx.application.Platform;
import javafx.scene.control.Alert.AlertType;
import rawDeepLearningClassifier.DLStatus;
import warnings.PamWarning;
public class DLWarningDialog {
private boolean warningShow;
private volatile boolean warningShow = false;
private DLSettingsPane rawDLSettingsPane;
public DLWarningDialog(DLSettingsPane rawDLSettingsPane) {
this.rawDLSettingsPane=rawDLSettingsPane;
}
/**
* Show a warning dialog for the status
* @param the status to show
*/
public void showWarningDialog(DLStatus dlWarning) {
switch(dlWarning) {
case MODEL_ENGINE_FAIL ->{
//special warning dialog
// show the warning
WarnOnceDialogFX wo = new WarnOnceDialogFX(null, dlWarning.getName(), dlWarning.getDescription(), AlertType.ERROR, null, null, "Ok", "Cancel", true);
wo.showDialog();
if (warningShow) return;
warningShow=true;
Platform.runLater(()->{
String helpURL = "http://www.pamguard.org/deeplearning/deep_learning_troubleshoot.html";
WarnOnce.showWarningFX(rawDLSettingsPane.getFXWindow(), dlWarning.getName(), dlWarning.getDescription() , AlertType.ERROR, helpURL, null,null, null, true);
warningShow = false;
// WarnOnce.showWarning( "Deep Learning Settings Warning", warningsF , WarnOnce.WARNING_MESSAGE);
});
// try {
// SwingUtilities.invokeAndWait(()->{
// WarnOnce.showWarning(dlWarning.getName(), dlWarning.getDescription(), WarnOnce.WARNING_MESSAGE,
// "https://www.pamguard.org/deeplearning/deep_lerning_troubleshoot.html", null, null, null, true);
// warningShow=false;
// });
// } catch (Exception e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
break;
}
default -> {
//default for most warnings.
@ -36,11 +55,10 @@ public class DLWarningDialog {
dlWarnings.add(DLSettingsPane.statusToWarnings(dlWarning));
showWarning(dlWarnings);
}
}
}
}
/**
* Show a warning dialog.
@ -49,10 +67,21 @@ public class DLWarningDialog {
public void showWarning(String dlWarning) {
this.warningShow = true;
Platform.runLater(()->{
WarnOnce.showWarningFX(null, "Deep Learning Settings Warning", dlWarning , AlertType.WARNING, true);
WarnOnce.showWarningFX(rawDLSettingsPane.getFXWindow(), "Deep Learning Warning", dlWarning , AlertType.ERROR, true);
warningShow = false;
// WarnOnce.showWarning( "Deep Learning Settings Warning", warningsF , WarnOnce.WARNING_MESSAGE);
});
// try {
// SwingUtilities.invokeAndWait(()->{
// WarnOnce.showWarning("Deep Learning Warning", dlWarning, WarnOnce.WARNING_MESSAGE,
// null, null, null, null, true);
// });
// } catch (Exception e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
warningShow = false;
// WarnOnce.showWarning( "Deep Learning Settings Warning", warningsF , WarnOnce.WARNING_MESSAGE);
}
@ -72,13 +101,10 @@ public class DLWarningDialog {
* @param dlWarnings - list of warnings - the most important will be shown.
*/
private void showWarning(ArrayList<PamWarning> dlWarnings) {
System.out.println("Show warning: " + dlWarnings);
if (warningShow) return; //not the best but don't show multiple dialogs on top of each other.
if (dlWarnings==null || dlWarnings.size()<1) return;
String warnings ="";
@ -93,10 +119,10 @@ public class DLWarningDialog {
this.warningShow = true;
final String warningsF = warnings;
final boolean errorF = error;
Platform.runLater(()->{
WarnOnce.showWarningFX(null, "Deep Learning Settings Warning", warningsF , errorF ? AlertType.ERROR : AlertType.WARNING, true);
WarnOnce.showWarningFX(rawDLSettingsPane.getFXWindow(), "Deep Learning Settings Warning", warningsF , errorF ? AlertType.ERROR : AlertType.WARNING, true);
warningShow = false;
// WarnOnce.showWarning( "Deep Learning Settings Warning", warningsF , WarnOnce.WARNING_MESSAGE);
});