Skip to content

103 gui performance #113

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 29, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 4 additions & 6 deletions src/main/java/jcs/JCS.java
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ public class JCS extends Thread {
private static UICallback uiCallback;

//private final List<RefreshEventListener> refreshEventListeners;

private JCS() {
//refreshEventListeners = new ArrayList<>();
}
Expand Down Expand Up @@ -215,9 +214,9 @@ public static void main(String[] args) {
jcsCommandStation = getJcsCommandStation();

if (persistentStore != null) {
if ("true".equalsIgnoreCase(System.getProperty("commandStation.autoconnect", "true"))) {
if ("true".equalsIgnoreCase(System.getProperty("commandStation.autoconnect", "false"))) {
if (jcsCommandStation != null) {
boolean connected = jcsCommandStation.connect();
boolean connected = jcsCommandStation.connectInBackground();
if (connected) {
logProgress("Connected with Command Station...");

Expand Down Expand Up @@ -287,9 +286,8 @@ private void startGui() {
jcsFrame.setVisible(true);
jcsFrame.toFront();
jcsFrame.showOverviewPanel();
if ("true".equalsIgnoreCase(System.getProperty("controller.autoconnect", "true"))) {
jcsFrame.connect(true);
}
boolean con = "true".equalsIgnoreCase(System.getProperty("controller.autoconnect", "true"));
jcsFrame.connect(con);
});

JCS.logProgress("JCS started...");
Expand Down
31 changes: 28 additions & 3 deletions src/main/java/jcs/commandStation/JCSCommandStation.java
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ public class JCSCommandStation {
* Operations to commandStations are performed in a worker thread to avoid blocking the EventDispatch thread.<br>
*/
public JCSCommandStation() {
this("true".equalsIgnoreCase(System.getProperty("skip.controller.autoconnect", "true")));
this("true".equalsIgnoreCase(System.getProperty("skip.controller.autoconnect", "false")));
}

private JCSCommandStation(boolean autoConnectController) {
Expand All @@ -107,7 +107,7 @@ private JCSCommandStation(boolean autoConnectController) {
supportedProtocols = new HashSet<>();

try {
if (autoConnectController && decoderController != null && decoderController.getCommandStationBean() != null || accessoryControllers.isEmpty() || feedbackControllers.isEmpty()) {
if (decoderController != null && (decoderController.getCommandStationBean() != null || !accessoryControllers.isEmpty() || !feedbackControllers.isEmpty()) && autoConnectController) {
connect();
Logger.trace(decoderController != null ? "Aquired " + decoderController.getClass().getSimpleName() : "Could not aquire a Command Station! " + (decoderController.isConnected() ? "Connected" : "NOT Connected"));
} else {
Expand All @@ -118,6 +118,30 @@ private JCSCommandStation(boolean autoConnectController) {
}
}

public final boolean connectInBackground() {
executor.execute(() -> connect());

long now = System.currentTimeMillis();
long timemax = now + 2000;

boolean con;
synchronized (this) {
con = decoderController.isConnected();
while (!con && timemax < now) {
try {
wait(500);
} catch (InterruptedException ex) {
Logger.trace(ex);
}
now = System.currentTimeMillis();
}
if (!(timemax < now)) {
Logger.trace("Timeout connecting...");
}
}
return con;
}

public final boolean connect() {
boolean decoderControllerConnected = false;
boolean allreadyConnected = false;
Expand Down Expand Up @@ -251,7 +275,8 @@ public CommandStationBean getCommandStationBean() {
if (decoderController != null) {
return decoderController.getCommandStationBean();
} else {
return null;
Logger.trace("Using the default CommandStationBean...");
return PersistenceFactory.getService().getDefaultCommandStation();
}
}

Expand Down
85 changes: 44 additions & 41 deletions src/main/java/jcs/persistence/H2PersistenceService.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,14 @@ public class H2PersistenceService implements PersistenceService {

protected final HashMap<String, Image> imageCache;
protected final HashMap<String, Image> functionImageCache;
protected final HashSet<String> nullFunctionImages;
protected final PropertyChangeSupport changeSupport;

public H2PersistenceService() {
initConnect();
imageCache = new HashMap<>();
functionImageCache = new HashMap<>();
nullFunctionImages = new HashSet<>();
changeSupport = new PropertyChangeSupport(this);
postInit();
}
Expand Down Expand Up @@ -453,57 +455,58 @@ public Image getFunctionImage(String imageName) {
@Override
public Image readImage(String imageName, boolean function) {
Image image = null;
if (imageName != null) {
String path;
if (imageName.contains(File.separator)) {
//Contains path seperators so assume it is a manual selected image
path = imageName;
} else {
//no path seperators so assume it is a synchonized command station icon
if (getDefaultCommandStation() != null) {
String shortName = getDefaultCommandStation().getShortName().toLowerCase();
path = System.getProperty("user.home") + File.separator + "jcs" + File.separator + "cache" + File.separator + shortName + File.separator;
if (!nullFunctionImages.contains(imageName)) {
if (imageName != null) {
String path;
if (imageName.contains(File.separator)) {
//Contains path seperators so assume it is a manual selected image
path = imageName;
} else {
path = System.getProperty("user.home") + File.separator + "jcs" + File.separator + "cache" + File.separator;
//no path seperators so assume it is a synchonized command station icon
if (getDefaultCommandStation() != null) {
String shortName = getDefaultCommandStation().getShortName().toLowerCase();
path = System.getProperty("user.home") + File.separator + "jcs" + File.separator + "cache" + File.separator + shortName + File.separator;
} else {
path = System.getProperty("user.home") + File.separator + "jcs" + File.separator + "cache" + File.separator;
}
}
}

if (function) {
if (!path.contains("/media/esu")) {
path = path + "zfunctions" + File.separator;
if (function) {
if (!path.contains("/media/esu")) {
path = path + "zfunctions" + File.separator;
}
}
}

File imgFile;
if (path.contains("/media/esu/")) {
//local resourse
imgFile = null;
} else if (path.contains(".")) {
imgFile = new File(path);
} else {
imgFile = new File(path + imageName.toLowerCase() + ".png");
}

if (imgFile != null && imgFile.exists()) {
try {
image = ImageIO.read(imgFile);
} catch (IOException e) {
Logger.trace("Image file " + imageName + ".png does not exists");
File imgFile;
if (path.contains("/media/esu/")) {
//local resourse
imgFile = null;
} else if (path.contains(".")) {
imgFile = new File(path);
} else {
imgFile = new File(path + imageName.toLowerCase() + ".png");
}
} else {
if (path.contains("/media")) {
URL iconUrl = getClass().getResource(path);

if (imgFile != null && imgFile.exists()) {
try {
image = ImageIO.read(iconUrl);
} catch (IOException | IllegalArgumentException e) {
Logger.trace("Image URL " + iconUrl + " does not exists");
image = ImageIO.read(imgFile);
} catch (IOException e) {
Logger.trace("Image file " + imageName + ".png does not exists");
}
} else {
if (path.contains("/media")) {
URL iconUrl = getClass().getResource(path);
try {
image = ImageIO.read(iconUrl);
} catch (IOException | IllegalArgumentException e) {
Logger.trace("Image URL " + path + " does not exists");
}
}
}
}

//TODO:
// should we attempt to obtain it now and cache it when available, but also when it is not
// available put a marker so that we are not trying over and over again...
// who should be responsable for the cache... the command controller, this class, or?
if (image == null) {
this.nullFunctionImages.add(imageName);
}
}
return image;
Expand Down
23 changes: 20 additions & 3 deletions src/main/java/jcs/ui/JCSFrame.java
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@
import jcs.util.VersionInfo;
import org.tinylog.Logger;
import jcs.commandStation.events.ConnectionEventListener;
import jcs.util.Ping;

/**
*
Expand Down Expand Up @@ -967,7 +968,22 @@ public void connect(boolean connect) {
boolean connected = false;
if (JCS.getJcsCommandStation() != null) {
if (connect) {
JCS.getJcsCommandStation().connect();
String ip = JCS.getJcsCommandStation().getCommandStationBean().getIpAddress();
if (Ping.IsReachable(ip)) {
if ("AWT-EventQueue-0".equals(Thread.currentThread().getName())) {
JCS.getJcsCommandStation().connectInBackground();
} else {

JCS.getJcsCommandStation().connect();
}
} else {
Logger.debug("Can't reach ip " + ip + "...");


JOptionPane.showMessageDialog(this, "Can't connect. "+ip+" is not reachable.", "Can't Connect", JOptionPane.ERROR_MESSAGE, null);


}

InfoBean info = JCS.getJcsCommandStation().getCommandStationInfo();
connected = JCS.getJcsCommandStation().isConnected();
Expand All @@ -981,7 +997,9 @@ public void connect(boolean connect) {
powerButton.setSelected(JCS.getJcsCommandStation().isPowerOn());
}
} else {
JCS.getJcsCommandStation().disconnect();
if (JCS.getJcsCommandStation().isConnected()) {
JCS.getJcsCommandStation().disconnect();
}
connectMI.setText("Connect");
}
}
Expand Down Expand Up @@ -1056,7 +1074,6 @@ private void startAutopilot() {
AutoPilot.runAutoPilot(autoPilotBtn.isSelected());
}


private void startAllLocsBtnActionPerformed(ActionEvent evt) {//GEN-FIRST:event_startAllLocsBtnActionPerformed
startAllLocomotives();
}//GEN-LAST:event_startAllLocsBtnActionPerformed
Expand Down
Loading
Loading