From 6726beb14f89461ed704e6f32a7f5231a0971565 Mon Sep 17 00:00:00 2001 From: Hendrik Ebbers Date: Fri, 11 Aug 2023 08:35:10 +0200 Subject: [PATCH] More classed moved to gui module (#7872) Signed-off-by: Hendrik Ebbers --- .../demo/crypto/CryptocurrencyDemoMain.java | 7 +- .../demo/hashgraph/HashgraphDemoMain.java | 5 +- .../demo/hello/HelloSwirldDemoMain.java | 6 +- .../com/swirlds/demo/stats/StatsDemoMain.java | 6 +- .../migration/MigrationTestingToolMain.java | 4 +- .../platform/PlatformTestingToolMain.java | 4 +- .../signing/StatsSigningTestingToolMain.java | 4 +- .../src/main/java/module-info.java | 3 +- .../java/com/swirlds/platform/Browser.java | 16 +- .../platform/gui/GuiPlatformAccessor.java | 99 ----- .../platform/gui/hashgraph/HashgraphGui.java | 2 +- .../gui/internal/BrowserWindowManager.java | 14 +- .../internal/PlatformHashgraphGuiSource.java | 6 +- .../platform/gui/internal/StateHierarchy.java | 1 + .../platform/gui/internal/SwirldMenu.java | 18 +- .../platform/gui/internal/WinBrowser.java | 5 +- .../gui/internal/WinTab2Consensus.java | 9 +- .../platform/gui/internal/WinTab2Stats.java | 378 +++--------------- .../gui/internal/WinTabAddresses.java | 2 +- .../platform/gui/internal/WinTabCalls.java | 2 +- .../platform/gui/internal/WinTabNetwork.java | 2 +- .../platform/gui/internal/WinTabPosts.java | 2 +- .../platform/gui/internal/WinTabSecurity.java | 11 +- .../platform/gui/internal/WinTabSwirlds.java | 7 +- .../swirlds-platform-gui/build.gradle.kts | 2 + .../main/java/com/swirlds/gui/GuiUtils.java | 2 + .../com/swirlds/gui/components/Chart.java | 364 +++++++++++++++++ .../gui/components/ChartLabelModel.java | 36 ++ .../{ => components}/PrePaintableJPanel.java | 2 +- .../{ => components}/ScrollableJPanel.java | 2 +- .../java/com/swirlds/gui/model/GuiModel.java | 138 +++++++ .../java/com/swirlds/gui/model}/InfoApp.java | 5 +- .../swirlds/gui/{ => model}/InfoEntity.java | 2 +- .../com/swirlds/gui/model}/InfoMember.java | 13 +- .../com/swirlds/gui/model}/InfoState.java | 6 +- .../com/swirlds/gui/model}/InfoSwirld.java | 5 +- .../com/swirlds/gui/model}/Reference.java | 4 +- .../java/com/swirlds/gui/model}/WordList.java | 8 +- .../src/main/java/module-info.java | 5 + 39 files changed, 689 insertions(+), 518 deletions(-) create mode 100644 platform-sdk/swirlds-platform-gui/src/main/java/com/swirlds/gui/components/Chart.java create mode 100644 platform-sdk/swirlds-platform-gui/src/main/java/com/swirlds/gui/components/ChartLabelModel.java rename platform-sdk/swirlds-platform-gui/src/main/java/com/swirlds/gui/{ => components}/PrePaintableJPanel.java (97%) rename platform-sdk/swirlds-platform-gui/src/main/java/com/swirlds/gui/{ => components}/ScrollableJPanel.java (97%) create mode 100644 platform-sdk/swirlds-platform-gui/src/main/java/com/swirlds/gui/model/GuiModel.java rename platform-sdk/{swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal => swirlds-platform-gui/src/main/java/com/swirlds/gui/model}/InfoApp.java (87%) rename platform-sdk/swirlds-platform-gui/src/main/java/com/swirlds/gui/{ => model}/InfoEntity.java (97%) rename platform-sdk/{swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal => swirlds-platform-gui/src/main/java/com/swirlds/gui/model}/InfoMember.java (76%) rename platform-sdk/{swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal => swirlds-platform-gui/src/main/java/com/swirlds/gui/model}/InfoState.java (86%) rename platform-sdk/{swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal => swirlds-platform-gui/src/main/java/com/swirlds/gui/model}/InfoSwirld.java (90%) rename platform-sdk/{swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal => swirlds-platform-gui/src/main/java/com/swirlds/gui/model}/Reference.java (99%) rename platform-sdk/{swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal => swirlds-platform-gui/src/main/java/com/swirlds/gui/model}/WordList.java (99%) diff --git a/platform-sdk/platform-apps/demos/CryptocurrencyDemo/src/main/java/com/swirlds/demo/crypto/CryptocurrencyDemoMain.java b/platform-sdk/platform-apps/demos/CryptocurrencyDemo/src/main/java/com/swirlds/demo/crypto/CryptocurrencyDemoMain.java index 72a2d41777d1..5f6bf41cc507 100644 --- a/platform-sdk/platform-apps/demos/CryptocurrencyDemo/src/main/java/com/swirlds/demo/crypto/CryptocurrencyDemoMain.java +++ b/platform-sdk/platform-apps/demos/CryptocurrencyDemo/src/main/java/com/swirlds/demo/crypto/CryptocurrencyDemoMain.java @@ -39,8 +39,8 @@ import com.swirlds.common.threading.framework.StoppableThread; import com.swirlds.common.threading.framework.config.StoppableThreadConfiguration; import com.swirlds.common.utility.AutoCloseableWrapper; +import com.swirlds.gui.model.GuiModel; import com.swirlds.platform.Browser; -import com.swirlds.platform.gui.GuiPlatformAccessor; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.util.Random; @@ -142,10 +142,9 @@ private void generateTransactions() { public void init(final Platform platform, final NodeId id) { this.platform = platform; this.selfId = id; - final int winNum = GuiPlatformAccessor.getInstance().getInstanceNumber(selfId); + final int winNum = GuiModel.getInstance().getInstanceNumber(selfId); this.console = createConsole(platform, winNum, true); // create the window, make it visible - GuiPlatformAccessor.getInstance() - .setAbout(platform.getSelfId(), "Cryptocurrency and stock market demo v. 1.0\n"); + GuiModel.getInstance().setAbout(platform.getSelfId(), "Cryptocurrency and stock market demo v. 1.0\n"); this.console.addKeyListener(keyListener); } diff --git a/platform-sdk/platform-apps/demos/HashgraphDemo/src/main/java/com/swirlds/demo/hashgraph/HashgraphDemoMain.java b/platform-sdk/platform-apps/demos/HashgraphDemo/src/main/java/com/swirlds/demo/hashgraph/HashgraphDemoMain.java index 70d80ee7698f..d8fd3b8932e6 100644 --- a/platform-sdk/platform-apps/demos/HashgraphDemo/src/main/java/com/swirlds/demo/hashgraph/HashgraphDemoMain.java +++ b/platform-sdk/platform-apps/demos/HashgraphDemo/src/main/java/com/swirlds/demo/hashgraph/HashgraphDemoMain.java @@ -37,6 +37,7 @@ import com.swirlds.common.system.address.Address; import com.swirlds.common.system.address.AddressBook; import com.swirlds.common.system.events.PlatformEvent; +import com.swirlds.gui.model.GuiModel; import com.swirlds.platform.Browser; import com.swirlds.platform.ParameterProvider; import com.swirlds.platform.gui.GuiPlatformAccessor; @@ -397,7 +398,7 @@ public void init(final Platform platform, final NodeId id) { this.selfId = id; final String[] parameters = ParameterProvider.getInstance().getParameters(); - GuiPlatformAccessor.getInstance() + GuiModel.getInstance() .setAbout( platform.getSelfId(), "Hashgraph Demo v. 1.1\n" + "\n" @@ -413,7 +414,7 @@ public void init(final Platform platform, final NodeId id) { + "Fame is true for green, false for blue, unknown for red.\n"); final Address address = platform.getAddressBook().getAddress(platform.getSelfId()); final int winCount = AddressBookNetworkUtils.getLocalAddressCount(platform.getAddressBook()); - final int winNum = GuiPlatformAccessor.getInstance().getInstanceNumber(platform.getSelfId()); + final int winNum = GuiModel.getInstance().getInstanceNumber(platform.getSelfId()); window = SwirldsGui.createWindow( platform, address, winCount, winNum, false); // Uses BorderLayout. Size is chosen by the Platform window.setLayout(new GridBagLayout()); // use a layout more powerful than BorderLayout diff --git a/platform-sdk/platform-apps/demos/HelloSwirldDemo/src/main/java/com/swirlds/demo/hello/HelloSwirldDemoMain.java b/platform-sdk/platform-apps/demos/HelloSwirldDemo/src/main/java/com/swirlds/demo/hello/HelloSwirldDemoMain.java index 93f7d9f9304d..859585bc8ca4 100644 --- a/platform-sdk/platform-apps/demos/HelloSwirldDemo/src/main/java/com/swirlds/demo/hello/HelloSwirldDemoMain.java +++ b/platform-sdk/platform-apps/demos/HelloSwirldDemo/src/main/java/com/swirlds/demo/hello/HelloSwirldDemoMain.java @@ -38,9 +38,9 @@ import com.swirlds.common.system.SwirldState; import com.swirlds.common.system.status.PlatformStatus; import com.swirlds.common.utility.AutoCloseableWrapper; +import com.swirlds.gui.model.GuiModel; import com.swirlds.platform.Browser; import com.swirlds.platform.SwirldsPlatform; -import com.swirlds.platform.gui.GuiPlatformAccessor; import java.nio.charset.StandardCharsets; /** @@ -79,9 +79,9 @@ public void init(final Platform platform, final NodeId id) { this.platform = (SwirldsPlatform) platform; this.selfId = id; - final int winNum = GuiPlatformAccessor.getInstance().getInstanceNumber(selfId); + final int winNum = GuiModel.getInstance().getInstanceNumber(selfId); this.console = createConsole(platform, winNum, true); // create the window, make it visible - GuiPlatformAccessor.getInstance().setAbout(platform.getSelfId(), "Hello Swirld v. 1.0\n"); + GuiModel.getInstance().setAbout(platform.getSelfId(), "Hello Swirld v. 1.0\n"); } @Override diff --git a/platform-sdk/platform-apps/demos/StatsDemo/src/main/java/com/swirlds/demo/stats/StatsDemoMain.java b/platform-sdk/platform-apps/demos/StatsDemo/src/main/java/com/swirlds/demo/stats/StatsDemoMain.java index f81b901f7627..cea0620b80a8 100644 --- a/platform-sdk/platform-apps/demos/StatsDemo/src/main/java/com/swirlds/demo/stats/StatsDemoMain.java +++ b/platform-sdk/platform-apps/demos/StatsDemo/src/main/java/com/swirlds/demo/stats/StatsDemoMain.java @@ -41,9 +41,9 @@ import com.swirlds.common.system.SwirldState; import com.swirlds.common.threading.framework.StoppableThread; import com.swirlds.common.threading.framework.config.StoppableThreadConfiguration; +import com.swirlds.gui.model.GuiModel; import com.swirlds.platform.Browser; import com.swirlds.platform.ParameterProvider; -import com.swirlds.platform.gui.GuiPlatformAccessor; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; @@ -222,10 +222,10 @@ public void init(final Platform platform, final NodeId id) { transPerEventMax = 1024; } if (!headless) { // create the window, make it visible - final int winNum = GuiPlatformAccessor.getInstance().getInstanceNumber(selfId); + final int winNum = GuiModel.getInstance().getInstanceNumber(selfId); console = createConsole(platform, winNum, true); } - GuiPlatformAccessor.getInstance() + GuiModel.getInstance() .setAbout( platform.getSelfId(), "Stats Demo v. 1.2\nThis writes statistics to a log file," diff --git a/platform-sdk/platform-apps/tests/MigrationTestingTool/src/main/java/com/swirlds/demo/migration/MigrationTestingToolMain.java b/platform-sdk/platform-apps/tests/MigrationTestingTool/src/main/java/com/swirlds/demo/migration/MigrationTestingToolMain.java index d5f6f5693f58..564ae1447b2c 100644 --- a/platform-sdk/platform-apps/tests/MigrationTestingTool/src/main/java/com/swirlds/demo/migration/MigrationTestingToolMain.java +++ b/platform-sdk/platform-apps/tests/MigrationTestingTool/src/main/java/com/swirlds/demo/migration/MigrationTestingToolMain.java @@ -24,10 +24,10 @@ import com.swirlds.common.system.SwirldMain; import com.swirlds.common.system.SwirldState; import com.swirlds.fcqueue.FCQueueStatistics; +import com.swirlds.gui.model.GuiModel; import com.swirlds.logging.payloads.ApplicationFinishedPayload; import com.swirlds.merkle.map.MerkleMapMetrics; import com.swirlds.platform.ParameterProvider; -import com.swirlds.platform.gui.GuiPlatformAccessor; import java.security.SignatureException; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -76,7 +76,7 @@ public void init(final Platform platform, final NodeId selfId) { maximumTransactionsPerNode = Integer.parseInt(parameters[1]); generator = new TransactionGenerator(seed); - GuiPlatformAccessor.getInstance().setAbout(platform.getSelfId(), "MigrationTestingApp"); + GuiModel.getInstance().setAbout(platform.getSelfId(), "MigrationTestingApp"); // Initialize application statistics initAppStats(); diff --git a/platform-sdk/platform-apps/tests/PlatformTestingTool/src/main/java/com/swirlds/demo/platform/PlatformTestingToolMain.java b/platform-sdk/platform-apps/tests/PlatformTestingTool/src/main/java/com/swirlds/demo/platform/PlatformTestingToolMain.java index 65a4ac7b5590..5ca7b64ebea0 100644 --- a/platform-sdk/platform-apps/tests/PlatformTestingTool/src/main/java/com/swirlds/demo/platform/PlatformTestingToolMain.java +++ b/platform-sdk/platform-apps/tests/PlatformTestingTool/src/main/java/com/swirlds/demo/platform/PlatformTestingToolMain.java @@ -78,6 +78,7 @@ import com.swirlds.demo.virtualmerkle.transaction.handler.VirtualMerkleTransactionHandler; import com.swirlds.fcqueue.FCQueue; import com.swirlds.fcqueue.FCQueueStatistics; +import com.swirlds.gui.model.GuiModel; import com.swirlds.logging.payloads.ApplicationFinishedPayload; import com.swirlds.logging.payloads.CreateTransactionFailedPayload; import com.swirlds.merkle.map.MerkleMap; @@ -85,7 +86,6 @@ import com.swirlds.merkle.map.test.pta.TransactionRecord; import com.swirlds.platform.Browser; import com.swirlds.platform.ParameterProvider; -import com.swirlds.platform.gui.GuiPlatformAccessor; import com.swirlds.virtualmap.internal.merkle.VirtualLeafNode; import java.io.File; import java.io.FileInputStream; @@ -539,7 +539,7 @@ public void init(Platform platform, NodeId id) { platform.getNotificationEngine().register(PlatformStatusChangeListener.class, this::platformStatusChange); registerReconnectCompleteListener(); - GuiPlatformAccessor.getInstance().setAbout(selfId, "Platform Testing Demo"); + GuiModel.getInstance().setAbout(selfId, "Platform Testing Demo"); try (final AutoCloseableWrapper wrapper = UnsafeMutablePTTStateAccessor.getInstance().getUnsafeMutableState(platform.getSelfId())) { final PlatformTestingToolState state = wrapper.get(); diff --git a/platform-sdk/platform-apps/tests/StatsSigningTestingTool/src/main/java/com/swirlds/demo/stats/signing/StatsSigningTestingToolMain.java b/platform-sdk/platform-apps/tests/StatsSigningTestingTool/src/main/java/com/swirlds/demo/stats/signing/StatsSigningTestingToolMain.java index 200d77624c5f..80d944968a65 100644 --- a/platform-sdk/platform-apps/tests/StatsSigningTestingTool/src/main/java/com/swirlds/demo/stats/signing/StatsSigningTestingToolMain.java +++ b/platform-sdk/platform-apps/tests/StatsSigningTestingTool/src/main/java/com/swirlds/demo/stats/signing/StatsSigningTestingToolMain.java @@ -44,9 +44,9 @@ import com.swirlds.common.threading.framework.config.ThreadConfiguration; import com.swirlds.demo.stats.signing.algorithms.ECSecP256K1Algorithm; import com.swirlds.demo.stats.signing.algorithms.X25519SigningAlgorithm; +import com.swirlds.gui.model.GuiModel; import com.swirlds.platform.Browser; import com.swirlds.platform.ParameterProvider; -import com.swirlds.platform.gui.GuiPlatformAccessor; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -170,7 +170,7 @@ public void init(final Platform platform, final NodeId id) { // they shouldn't both be -1, so set one of them transPerEventMax = 1024; } - GuiPlatformAccessor.getInstance() + GuiModel.getInstance() .setAbout( platform.getSelfId(), "Stats Signing Demo v. 1.3\nThis writes statistics to a log file," diff --git a/platform-sdk/swirlds-common/src/main/java/module-info.java b/platform-sdk/swirlds-common/src/main/java/module-info.java index ec1997d5be13..8cd17aaa94af 100644 --- a/platform-sdk/swirlds-common/src/main/java/module-info.java +++ b/platform-sdk/swirlds-common/src/main/java/module-info.java @@ -153,7 +153,8 @@ com.swirlds.demo.platform, com.swirlds.jrs, com.swirlds.platform, - com.swirlds.platform.test; + com.swirlds.platform.test, + com.swirlds.gui; requires transitive com.swirlds.base; requires com.swirlds.config; diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/Browser.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/Browser.java index a76e4d782c9b..e026570ab913 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/Browser.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/Browser.java @@ -80,6 +80,10 @@ import com.swirlds.config.api.source.ConfigSource; import com.swirlds.fchashmap.config.FCHashMapConfig; import com.swirlds.gui.WindowConfig; +import com.swirlds.gui.model.GuiModel; +import com.swirlds.gui.model.InfoApp; +import com.swirlds.gui.model.InfoMember; +import com.swirlds.gui.model.InfoSwirld; import com.swirlds.jasperdb.config.JasperDbConfig; import com.swirlds.logging.payloads.NodeAddressMismatchPayload; import com.swirlds.logging.payloads.NodeStartPayload; @@ -98,10 +102,6 @@ import com.swirlds.platform.event.tipset.EventCreationConfig; import com.swirlds.platform.gossip.chatter.config.ChatterConfig; import com.swirlds.platform.gossip.sync.config.SyncConfig; -import com.swirlds.platform.gui.GuiPlatformAccessor; -import com.swirlds.platform.gui.internal.InfoApp; -import com.swirlds.platform.gui.internal.InfoMember; -import com.swirlds.platform.gui.internal.InfoSwirld; import com.swirlds.platform.gui.internal.StateHierarchy; import com.swirlds.platform.health.OSHealthChecker; import com.swirlds.platform.health.clock.OSClockSpeedSourceChecker; @@ -315,7 +315,7 @@ private Browser(@NonNull final Set localNodesToStart) throws IOException startPlatforms(configuration, appDefinition, appMains); // create the browser window, which uses those Statistics objects - showBrowserWindow(); + showBrowserWindow(null); for (final Frame f : Frame.getFrames()) { if (!f.equals(getBrowserWindow())) { f.toFront(); @@ -695,9 +695,9 @@ private Collection createLocalPlatforms( initialState.get(), addressBookInitializer.getInitialAddressBook()); } - GuiPlatformAccessor.getInstance().setPlatformName(nodeId, platformName); - GuiPlatformAccessor.getInstance().setSwirldId(nodeId, appDefinition.getSwirldId()); - GuiPlatformAccessor.getInstance().setInstanceNumber(nodeId, instanceNumber); + GuiModel.getInstance().setPlatformName(nodeId, platformName); + GuiModel.getInstance().setSwirldId(nodeId, appDefinition.getSwirldId()); + GuiModel.getInstance().setInstanceNumber(nodeId, instanceNumber); platform = new SwirldsPlatform( platformContext, diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/GuiPlatformAccessor.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/GuiPlatformAccessor.java index d5f3d562d8af..ac2716f6c3cb 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/GuiPlatformAccessor.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/GuiPlatformAccessor.java @@ -42,10 +42,6 @@ @Deprecated(forRemoval = true) public final class GuiPlatformAccessor { - private final Map aboutStrings = new ConcurrentHashMap<>(); - private final Map platformNames = new ConcurrentHashMap<>(); - private final Map swirldIds = new ConcurrentHashMap<>(); - private final Map instanceNumbers = new ConcurrentHashMap<>(); private final Map shadowGraphs = new ConcurrentHashMap<>(); private final Map stateManagementComponents = new ConcurrentHashMap<>(); private final Map> consensusReferences = new ConcurrentHashMap<>(); @@ -63,101 +59,6 @@ public static GuiPlatformAccessor getInstance() { private GuiPlatformAccessor() {} - /** - * The SwirldMain calls this to set the string that is shown when the user chooses "About" from the Swirlds menu in - * the upper-right corner of the window. It is recommended that this be a short string that includes the name of the - * app, the version number, and the year. - * - * @param nodeId the ID of the node - * @param about wha should show in the "about" window from the menu - */ - public void setAbout(@NonNull final NodeId nodeId, @NonNull final String about) { - Objects.requireNonNull(nodeId, "nodeId must not be null"); - Objects.requireNonNull(about, "about must not be null"); - aboutStrings.put(nodeId, about); - } - - /** - * Get the "about" string, or an empty string if none has been set. - * - * @param nodeId the ID of the node - * @return an "about" string - */ - public String getAbout(@NonNull final NodeId nodeId) { - Objects.requireNonNull(nodeId, "nodeId must not be null"); - return aboutStrings.getOrDefault(nodeId, ""); - } - - /** - * Set a platform name, given the node ID. - * - * @param nodeId the ID of the node - * @param platformName a platform name - */ - public void setPlatformName(@NonNull final NodeId nodeId, @NonNull final String platformName) { - Objects.requireNonNull(nodeId, "nodeId must not be null"); - Objects.requireNonNull(platformName, "platformName must not be null"); - platformNames.put(nodeId, platformName); - } - - /** - * Get a platform name, given the node ID, or an empty string if none has been set. - * - * @param nodeId the ID of the node - * @return a platform name - */ - @NonNull - public String getPlatformName(@NonNull final NodeId nodeId) { - Objects.requireNonNull(nodeId, "nodeId must not be null"); - return platformNames.getOrDefault(nodeId, ""); - } - - /** - * Set the swirld ID for a node. - * - * @param nodeId the ID of the node - * @param swirldId the swirld ID - */ - public void setSwirldId(@NonNull final NodeId nodeId, @NonNull final byte[] swirldId) { - Objects.requireNonNull(nodeId, "nodeId must not be null"); - Objects.requireNonNull(swirldId, "swirldId must not be null"); - swirldIds.put(nodeId, swirldId); - } - - /** - * Get the swirld ID for a node, or null if none is set. - * - * @param nodeId the ID of the node - * @return the swirld ID - */ - @Nullable - public byte[] getSwirldId(@NonNull final NodeId nodeId) { - Objects.requireNonNull(nodeId, "nodeId must not be null"); - return swirldIds.getOrDefault(nodeId, null); - } - - /** - * Set the instance number for a node. - * - * @param nodeId the ID of the node - * @param instanceNumber the instance number - */ - public void setInstanceNumber(@NonNull final NodeId nodeId, final int instanceNumber) { - Objects.requireNonNull(nodeId, "nodeId must not be null"); - instanceNumbers.put(nodeId, instanceNumber); - } - - /** - * Get the instance number for a node, or -1 if none is set. - * - * @param nodeId the ID of the node - * @return the instance number - */ - public int getInstanceNumber(@NonNull final NodeId nodeId) { - Objects.requireNonNull(nodeId, "nodeId must not be null"); - return instanceNumbers.getOrDefault(nodeId, -1); - } - /** * Set the shadow graph for a node. * diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/hashgraph/HashgraphGui.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/hashgraph/HashgraphGui.java index fc7c024dc2d7..de387c3f0b84 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/hashgraph/HashgraphGui.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/hashgraph/HashgraphGui.java @@ -17,7 +17,7 @@ package com.swirlds.platform.gui.hashgraph; import com.swirlds.gui.GuiUtils; -import com.swirlds.gui.PrePaintableJPanel; +import com.swirlds.gui.components.PrePaintableJPanel; import com.swirlds.gui.hashgraph.HashgraphGuiSource; import com.swirlds.platform.gui.hashgraph.internal.CachingGuiSource; import com.swirlds.platform.gui.hashgraph.internal.HashgraphGuiControls; diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/BrowserWindowManager.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/BrowserWindowManager.java index 8302ec80c1a2..64b5a0e6be24 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/BrowserWindowManager.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/BrowserWindowManager.java @@ -16,8 +16,9 @@ package com.swirlds.platform.gui.internal; -import com.swirlds.gui.ScrollableJPanel; +import com.swirlds.gui.components.ScrollableJPanel; import com.swirlds.platform.SwirldsPlatform; +import edu.umd.cs.findbugs.annotations.Nullable; import java.awt.GraphicsEnvironment; import java.util.ArrayList; import java.util.Collection; @@ -86,15 +87,7 @@ public static Collection getPlatforms() { * * @param comp the index of the tab to select */ - public static void showBrowserWindow(final ScrollableJPanel comp) { - showBrowserWindow(); - getBrowserWindow().goTab(comp); - } - - /** - * Make the browser window visible. If it doesn't yet exist, then create it. - */ - public static void showBrowserWindow() { + public static void showBrowserWindow(@Nullable final ScrollableJPanel comp) { if (GraphicsEnvironment.isHeadless()) { return; } @@ -103,5 +96,6 @@ public static void showBrowserWindow() { return; } setBrowserWindow(new WinBrowser(new PlatformHashgraphGuiSource())); + getBrowserWindow().goTab(comp); } } diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/PlatformHashgraphGuiSource.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/PlatformHashgraphGuiSource.java index 259a1a0ec1be..8ddf3ce10ffb 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/PlatformHashgraphGuiSource.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/PlatformHashgraphGuiSource.java @@ -16,8 +16,8 @@ package com.swirlds.platform.gui.internal; +import com.swirlds.common.system.Platform; import com.swirlds.common.system.address.AddressBook; -import com.swirlds.platform.SwirldsPlatform; import com.swirlds.platform.gossip.shadowgraph.ShadowGraph; import com.swirlds.platform.gui.GuiPlatformAccessor; import com.swirlds.platform.gui.hashgraph.internal.ShadowgraphGuiSource; @@ -40,14 +40,14 @@ public boolean isReady() { @Override public ShadowGraph getShadowGraph() { - final SwirldsPlatform platform = getPlatform(); + final Platform platform = getPlatform(); if (platform == null) { return null; } return GuiPlatformAccessor.getInstance().getShadowGraph(platform.getSelfId()); } - private SwirldsPlatform getPlatform() { + private Platform getPlatform() { return WinBrowser.memberDisplayed.getPlatform(); } } diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/StateHierarchy.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/StateHierarchy.java index deb3ed136f3b..09a16479d5b5 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/StateHierarchy.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/StateHierarchy.java @@ -20,6 +20,7 @@ import static com.swirlds.common.io.utility.FileUtils.rethrowIO; import com.swirlds.common.utility.CommonUtils; +import com.swirlds.gui.model.InfoApp; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/SwirldMenu.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/SwirldMenu.java index 1c505e841201..893dc90b1e40 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/SwirldMenu.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/SwirldMenu.java @@ -18,13 +18,13 @@ import static com.swirlds.common.system.SystemExitUtils.exitSystem; import static com.swirlds.logging.LogMarker.EXCEPTION; -import static com.swirlds.platform.gui.internal.BrowserWindowManager.showBrowserWindow; import com.swirlds.common.system.Platform; import com.swirlds.common.system.SystemExitCode; import com.swirlds.common.utility.PlatformVersion; -import com.swirlds.platform.SwirldsPlatform; -import com.swirlds.platform.gui.GuiPlatformAccessor; +import com.swirlds.gui.components.ScrollableJPanel; +import com.swirlds.gui.model.GuiModel; +import edu.umd.cs.findbugs.annotations.Nullable; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; @@ -102,7 +102,7 @@ public class SwirldMenu extends JPanel { * @param size * the height and width of the icon, in pixels */ - public static void addTo(SwirldsPlatform platform, JFrame window, int size) { + public static void addTo(Platform platform, JFrame window, int size) { addTo(platform, window, size, Color.BLUE, true); } @@ -292,9 +292,7 @@ public void actionPerformed(ActionEvent e) { case "About": int choice = JOptionPane.showOptionDialog( null, // parentCompoinent - (platform == null - ? "" - : GuiPlatformAccessor.getInstance().getAbout(platform.getSelfId())) + (platform == null ? "" : GuiModel.getInstance().getAbout(platform.getSelfId())) + "\n\n" + PlatformVersion.locateOrDefault().license(), // message "About this app", // title @@ -314,7 +312,7 @@ public void actionPerformed(ActionEvent e) { } break; case "Browser": - showBrowserWindow(); + showBrowserWindow(null); break; case "Call": showBrowserWindow(WinBrowser.tabCalls); @@ -331,6 +329,10 @@ public void actionPerformed(ActionEvent e) { } } + private void showBrowserWindow(@Nullable final ScrollableJPanel comp) { + BrowserWindowManager.showBrowserWindow(null); + } + /** * Popup a dialog box with an OK button, giving a scrollable view of the given HTML file within the .jar * file. diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/WinBrowser.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/WinBrowser.java index 341087608d2e..5e8e8e1fdf29 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/WinBrowser.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/WinBrowser.java @@ -22,8 +22,9 @@ import com.swirlds.gui.GuiConstants; import com.swirlds.gui.GuiUtils; -import com.swirlds.gui.ScrollableJPanel; +import com.swirlds.gui.components.ScrollableJPanel; import com.swirlds.gui.hashgraph.HashgraphGuiSource; +import com.swirlds.gui.model.InfoMember; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; @@ -67,7 +68,7 @@ public class WinBrowser extends JFrame { /** refresh the screen every this many milliseconds */ final int refreshPeriod = 500; /** the InfoMember that is currently being shown by all tabs in the browser window */ - static volatile InfoMember memberDisplayed = null; + public static volatile InfoMember memberDisplayed = null; /** have all the tabs been initialized yet? */ private boolean didInit = false; diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/WinTab2Consensus.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/WinTab2Consensus.java index 7c11d0b2d2bb..a65b48cedd7b 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/WinTab2Consensus.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/WinTab2Consensus.java @@ -18,10 +18,11 @@ import static com.swirlds.gui.GuiUtils.wrap; +import com.swirlds.common.system.Platform; import com.swirlds.gui.GuiUtils; -import com.swirlds.gui.PrePaintableJPanel; +import com.swirlds.gui.components.PrePaintableJPanel; +import com.swirlds.gui.model.GuiModel; import com.swirlds.platform.Consensus; -import com.swirlds.platform.SwirldsPlatform; import com.swirlds.platform.components.state.StateManagementComponent; import com.swirlds.platform.gui.GuiPlatformAccessor; import com.swirlds.platform.state.signed.SignedStateInfo; @@ -55,9 +56,9 @@ public void prePaint() { if (WinBrowser.memberDisplayed == null) { return; } - SwirldsPlatform platform = WinBrowser.memberDisplayed.getPlatform(); + Platform platform = WinBrowser.memberDisplayed.getPlatform(); String s = ""; - s += GuiPlatformAccessor.getInstance().getPlatformName(platform.getSelfId()); + s += GuiModel.getInstance().getPlatformName(platform.getSelfId()); final Consensus consensus = GuiPlatformAccessor.getInstance().getConsensus(platform.getSelfId()); long r1 = consensus.getDeleteRound(); long r2 = consensus.getFameDecidedBelow(); diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/WinTab2Stats.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/WinTab2Stats.java index 82e65f83eb5c..333603397ea5 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/WinTab2Stats.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/WinTab2Stats.java @@ -23,12 +23,12 @@ import com.swirlds.common.config.BasicConfig; import com.swirlds.common.metrics.LegacyMetric; import com.swirlds.common.metrics.Metric; -import com.swirlds.common.metrics.statistics.internal.StatsBuffer; import com.swirlds.gui.GuiConstants; import com.swirlds.gui.GuiUtils; -import com.swirlds.gui.PrePaintableJPanel; +import com.swirlds.gui.components.Chart; +import com.swirlds.gui.components.ChartLabelModel; +import com.swirlds.gui.components.PrePaintableJPanel; import java.awt.Color; -import java.awt.Dimension; import java.awt.Font; import java.awt.Graphics; import java.awt.GridBagConstraints; @@ -48,7 +48,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -class WinTab2Stats extends PrePaintableJPanel { +class WinTab2Stats extends PrePaintableJPanel implements ChartLabelModel { private static final long serialVersionUID = 1L; public static final int CHART_WIDTH = 750; public static final int CHART_HEIGHT = 400; @@ -62,7 +62,6 @@ class WinTab2Stats extends PrePaintableJPanel { private JTextArea descriptions; private final Color LIGHT_GRAY = new Color(0.9f, 0.9f, 0.9f); - private final Color DARK_GRAY = new Color(0.8f, 0.8f, 0.8f); /** all the TextArea objects, one per statistic */ private JLabel[] statBoxes; @@ -108,326 +107,6 @@ public WinTab2Stats() { } } - /** a JPanel with one chart that plots a statistic vs. time, either all history or recent */ - private class Chart extends JPanel { - /** for serializing */ - private static final long serialVersionUID = 1L; - /** {@link Metric} of this chart */ - private final transient Metric metric; - /** is this all of history (as opposed to only recent)? */ - private boolean allHistory; - /** the number of labels to generate */ - private long numSteps; - - int stringHeight; - int stringHeightNoDesc; - int minXs; - int maxXs; - int minYs; - int maxYs; - double minXb; - double maxXb; - double minYb; - double maxYb; - - /** - * A chart that displays the history of a statistic from a StatsBuffer - * - * @param width - * width of the panel in pixels - * @param height - * height of the panel in pixels - * @param allHistory - * is this all of history (as opposed to only recent)? - * @param metric - * {@link Metric} of this chart - */ - Chart(int width, int height, boolean allHistory, final Metric metric) { - this.setPreferredSize(new Dimension(width, height)); - this.allHistory = allHistory; - this.metric = metric; - this.setBackground(Color.WHITE); - } - - /** - * translate an x value from the buffer to screen coordinates, clipping it to lie inside the chart. - * - * @param x - * the x parameter from the buffer - * @return the x screen coordinate - */ - private int scaleX(double x) { - if (minXb == maxXb) { // if only one data point, - return (minXs + maxXs) / 2; // then display it in the middle - } - return (int) (Math.min(1, Math.max(0, (x - minXb) / (maxXb - minXb))) * (maxXs - minXs) + minXs); - } - - /** - * translate a y value from the buffer to screen coordinates, clipping it to lie inside the chart. - * - * @param y - * the y parameter from the buffer - * @return the y screen coordinate - */ - private int scaleY(double y) { - if (minYb == maxYb) { // if a value has been constant throughout history, - return (minYs + maxYs) / 2; // then display it in the middle - } - return (int) (maxYs - Math.min(1, Math.max(0, (y - minYb) / (maxYb - minYb))) * (maxYs - minYs)); - } - - /** - * all x axis labels reflect x values divided by this. This is 1 for seconds, 60 for minutes, etc. - */ - double xDivisor = 1; - /** - * the units for the x axis labels. If "seconds", then xDivisor is 1, if "minutes", then 60, etc. - */ - String xUnits = "seconds"; - - /** - * Check if "step" is a good step size. If so, set numSteps to the number of labels it will - * generate, and return true. Else return false. - * - * @param step - * the proposed step size - * @param min - * the minimum value of all the data - * @param max - * the maximum value of all the data - * @return true if this step size won't produce too many labels - */ - private boolean good(double step, double min, double max) { - if (step <= 0 || max < min) { - return false; - } - numSteps = 1 + Math.round(Math.ceil(max / step) - Math.floor(min / step)); - return 4 <= numSteps && numSteps <= 7; - } - - /** - * Create the y labels and choose their positions - * - * This method "returns" xLabel and xLabelVal, by changing those class variables. - */ - private void findYLabel() { - if (maxYb == minYb) { - String s = String.format("%,.0f", minYb); - yLabel = new String[] {s}; - yLabelVal = new double[] {minYb}; - return; - } - double step10 = Math.pow(10, Math.floor(Math.log10(maxYb - minYb)) - 1); - double step = 1; - for (int i = 0; i < 4; i++) { // find a step that results in a good number of labels - if (good(step = step10, minYb, maxYb)) { - break; - } - if (good(step = step10 * 2, minYb, maxYb)) { - break; - } - if (good(step = step10 * 5, minYb, maxYb)) { - break; - } - step10 *= 10; - } - // number of decimal places to show, for the given step (0 if showing an integer is ok) - long decimals = Math.round(Math.max(0, -Math.floor(Math.log10(step)))); - double epsilon = Math.pow(10, -1 - decimals); // if showing 2 decimal places, this is 0.001 - double localMaxYb = Math.ceil(maxYb / step) * step + epsilon; - yLabel = new String[(int) numSteps - 2]; - yLabelVal = new double[(int) numSteps - 2]; - for (int i = 0; i < numSteps - 2; i++) { - yLabelVal[i] = localMaxYb - (i + 1) * step + epsilon; - yLabel[i] = String.format("%,." + decimals + "f", yLabelVal[i]); - } - } - - /** - * Create the x labels and choose their positions - * - * This method "returns" xLabel and xLabelVal, by changing those class variables. - */ - private void findXLabel() { - if (maxXb <= minXb) { - String s = String.format("%,.0f", minXb); - xLabel = new String[] {s}; - xLabelVal = new double[] {minXb}; - return; - } - double step10 = Math.pow(10, Math.floor(Math.log10(maxXb - minXb)) - 1); - double step = 1; - for (int i = 0; i < 4; i++) { // find a step that results in a good number of labels - if (good(step = step10, minXb, maxXb)) { - break; - } - if (good(step = step10 * 2, minXb, maxXb)) { - break; - } - if (good(step = step10 * 5, minXb, maxXb)) { - break; - } - step10 *= 10; - } - if (!good(step, minXb, maxXb)) { - // couldn't find a good step size. Maybe numSteps or the data are NaN? - numSteps = 4; - step = 1; - } - // number of decimal places to show, for the given step (0 if showing an integer is ok) - long decimals = Math.round(Math.max(0, -Math.floor(Math.log10(step)))); - double epsilon = Math.pow(10, -1 - decimals); // if showing 2 decimal places, this is 0.001 - double localMaxXb = Math.ceil(maxXb / step) * step + epsilon; - xLabel = new String[(int) numSteps - 2]; - xLabelVal = new double[(int) numSteps - 2]; - for (int i = 0; i < numSteps - 2; i++) { - xLabelVal[i] = localMaxXb - (i + 1) * step + epsilon; - xLabel[i] = String.format("%,." + decimals + "f", xLabelVal[i]); - } - } - - @Override - protected void paintComponent(Graphics g) { - super.paintComponent(g); - try { - StatsBuffer buffer; - if (metric instanceof LegacyMetric legacyMetric) { - if (allHistory) { - buffer = legacyMetric.getStatsBuffered().getAllHistory(); - } else { - buffer = legacyMetric.getStatsBuffered().getRecentHistory(); - } - } else { - buffer = new StatsBuffer(0, 0, 0); - } - - minXs = 120; - maxXs = getWidth() - 55; - minYs = 40; - maxYs = getHeight() - 50; - - minXb = buffer.xMin(); - maxXb = buffer.xMax(); - minYb = buffer.yMin(); - maxYb = buffer.yMax(); - - if (maxXb - minXb > 60 * 60 * 24 * 365) { - xDivisor = 60 * 60 * 24 * 365; - xUnits = "years"; - } else if (maxXb - minXb > 60 * 60 * 24) { - xDivisor = 60 * 60 * 24; - xUnits = "days"; - } else if (maxXb - minXb > 60 * 60) { - xDivisor = 60 * 60; - xUnits = "hours"; - } else if (maxXb - minXb > 60 * 1.1) { - xDivisor = 60; - xUnits = "minutes"; - } else { - xDivisor = 1; - xUnits = "seconds"; - } - - g.setColor(Color.BLACK); - stringHeight = g.getFontMetrics().getHeight(); - stringHeightNoDesc = - g.getFontMetrics().getHeight() - g.getFontMetrics().getDescent(); - String title = metric.getName() + " vs. time for " + (allHistory ? "all" : "recent") + " history"; - - if (buffer.numBins() == 0) { - final BasicConfig basicConfig = WinBrowser.memberDisplayed - .getPlatform() - .getContext() - .getConfiguration() - .getConfigData(BasicConfig.class); - final String s = - String.format("Skipping the first %,.0f seconds ...", basicConfig.statsSkipSeconds()); - final int w = g.getFontMetrics().stringWidth(s); - g.drawString(s, (minXs + maxXs - w) / 2, (minYs + maxYs) / 2); - g.drawLine(minXs, maxYs, maxXs, maxYs); // x axis - g.drawLine(minXs, minYs, minXs, maxYs); // y axis - } - for (int i = 0; i < buffer.numBins(); i++) { - g.setColor(LIGHT_GRAY); - int x0, y0, x1, y1; - x0 = scaleX(i == 0 ? buffer.xMin(i) : buffer.xMax(i - 1)); // eliminate gaps - y0 = scaleY(buffer.yMax(i)); - x1 = scaleX(buffer.xMax(i)); - y1 = scaleY(buffer.yMin(i)); - g.fillRect(x0, y0, x1 - x0, y1 - y0); - g.setColor(DARK_GRAY); - x0 = scaleX(i == 0 ? buffer.xMin(i) : buffer.xMax(i - 1)); // eliminate gaps - y0 = scaleY(buffer.yAvg(i) + buffer.yStd(i)); - x1 = scaleX(buffer.xMax(i)); - y1 = scaleY(buffer.yAvg(i) - buffer.yStd(i)); - g.fillRect(x0, y0, x1 - x0, y1 - y0); - g.setColor(Color.BLUE); - if (i > 0) { - x0 = scaleX(buffer.xAvg(i - 1)); - y0 = scaleY(buffer.yAvg(i - 1)); - x1 = scaleX(buffer.xAvg(i)); - y1 = scaleY(buffer.yAvg(i)); - g.drawLine(x0, y0, x1, y1); - } - } - g.setColor(Color.BLACK); - - // draw title and x axis name: - - int w = g.getFontMetrics().stringWidth(title); - g.drawString(title, minXs + (maxXs - minXs - w) / 2, stringHeight); - String s = "Time in the past (in " + xUnits + ")"; - w = g.getFontMetrics().stringWidth(s); - g.drawString(s, minXs + (maxXs - minXs - w) / 2, getHeight() - stringHeight); - - if (buffer.numBins() == 0) { - return; // don't draw labels when there's no data - } - - // draw X axis labels: - - double tt = minXb; - minXb = (minXb - tt) / xDivisor; - maxXb = (maxXb - tt) / xDivisor; - double t2 = (maxXb - minXb) / 50; - minXb -= t2; // make sure the 0 label is displayed - findXLabel(); // labels reflect "time ago", scaled to current units - minXb += t2; - minXb = minXb * xDivisor + tt; - maxXb = maxXb * xDivisor + tt; - for (int i = 0; i < xLabelVal.length; i++) { - xLabelVal[i] = xLabelVal[i] * xDivisor + tt; - } - - for (int i = 0; i < xLabel.length; i++) { - int x = maxXs - (scaleX(xLabelVal[i]) - minXs); - int stringWidth = g.getFontMetrics().stringWidth(xLabel[i]); - g.drawLine(x, maxYs + 4, x, maxYs - 4); - g.drawString(xLabel[i], x - stringWidth / 2 + 1, maxYs + stringHeight + 5); - } - - // draw Y axis labels: - - findYLabel(); - - for (int i = 0; i < yLabel.length; i++) { - int y = scaleY(yLabelVal[i]); - int stringWidth = g.getFontMetrics().stringWidth(yLabel[i]); - g.drawLine(minXs - 4, y, minXs + 4, y); - g.drawString(yLabel[i], minXs - stringWidth - 10, y + stringHeightNoDesc / 2 - 1); - } - - // draw X and Y axes - - g.drawLine(minXs, maxYs, maxXs, maxYs); // x axis - g.drawLine(minXs, minYs, minXs, maxYs); // y axis - } catch (Exception e) { - logger.error(EXCEPTION.getMarker(), "error while painting: {}", e); - } - } - } - /** * make visible the chart with the given index, and turn its box blue. This is also the index of the * statistic that it shows. @@ -530,8 +209,13 @@ public void prePaint() { statBoxes[i].setOpaque(true); charts[j] = new JPanel(); charts[j].setBackground(Color.WHITE); - charts[j].add(new Chart(CHART_WIDTH, CHART_HEIGHT, false, metric)); - charts[j].add(new Chart(CHART_WIDTH, CHART_HEIGHT, true, metric)); + final BasicConfig basicConfig = WinBrowser.memberDisplayed + .getPlatform() + .getContext() + .getConfiguration() + .getConfigData(BasicConfig.class); + charts[j].add(new Chart(this, CHART_WIDTH, CHART_HEIGHT, basicConfig, false, metric)); + charts[j].add(new Chart(this, CHART_WIDTH, CHART_HEIGHT, basicConfig, true, metric)); charts[j].setVisible(false); // use "visible" as a flag to indicate it's in the container final int jj = j; // effectively final so the listener can use it statBoxes[i].addMouseListener(new MouseAdapter() { @@ -608,4 +292,44 @@ private static String format(final Metric metric) { } return ""; } + + @Override + public void setYLabels(String[] labels) { + this.yLabel = labels; + } + + @Override + public void setYLabelValues(double[] values) { + this.yLabelVal = values; + } + + @Override + public void setXLabels(String[] labels) { + this.xLabel = labels; + } + + @Override + public void setXLabelValues(double[] values) { + this.xLabelVal = values; + } + + @Override + public String[] getYLabels() { + return yLabel; + } + + @Override + public double[] getYLabelValues() { + return yLabelVal; + } + + @Override + public String[] getXLabels() { + return xLabel; + } + + @Override + public double[] getXLabelValues() { + return xLabelVal; + } } diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/WinTabAddresses.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/WinTabAddresses.java index fb0f8887b0b1..1e2f6facd02d 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/WinTabAddresses.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/WinTabAddresses.java @@ -22,7 +22,7 @@ import com.swirlds.common.system.Platform; import com.swirlds.common.system.address.Address; import com.swirlds.gui.GuiUtils; -import com.swirlds.gui.PrePaintableJPanel; +import com.swirlds.gui.components.PrePaintableJPanel; import javax.swing.JTextArea; /** diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/WinTabCalls.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/WinTabCalls.java index 834d256f1f1c..a24dbde1ffa6 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/WinTabCalls.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/WinTabCalls.java @@ -17,7 +17,7 @@ package com.swirlds.platform.gui.internal; import com.swirlds.gui.GuiConstants; -import com.swirlds.gui.PrePaintableJPanel; +import com.swirlds.gui.components.PrePaintableJPanel; import javax.swing.JLabel; /** diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/WinTabNetwork.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/WinTabNetwork.java index 02586cdec072..f58ec5ed6c3e 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/WinTabNetwork.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/WinTabNetwork.java @@ -16,7 +16,7 @@ package com.swirlds.platform.gui.internal; -import com.swirlds.gui.PrePaintableJPanel; +import com.swirlds.gui.components.PrePaintableJPanel; import com.swirlds.gui.hashgraph.HashgraphGuiSource; import com.swirlds.platform.gui.hashgraph.HashgraphGui; import java.awt.Color; diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/WinTabPosts.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/WinTabPosts.java index c387408d71c8..e85057c7f228 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/WinTabPosts.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/WinTabPosts.java @@ -17,7 +17,7 @@ package com.swirlds.platform.gui.internal; import com.swirlds.gui.GuiConstants; -import com.swirlds.gui.PrePaintableJPanel; +import com.swirlds.gui.components.PrePaintableJPanel; import javax.swing.JLabel; /** diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/WinTabSecurity.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/WinTabSecurity.java index 036778935bf2..0f0ebebed721 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/WinTabSecurity.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/WinTabSecurity.java @@ -18,10 +18,11 @@ import static com.swirlds.gui.GuiUtils.wrap; +import com.swirlds.common.system.Platform; import com.swirlds.gui.GuiUtils; -import com.swirlds.gui.PrePaintableJPanel; -import com.swirlds.platform.SwirldsPlatform; -import com.swirlds.platform.gui.GuiPlatformAccessor; +import com.swirlds.gui.components.PrePaintableJPanel; +import com.swirlds.gui.model.GuiModel; +import com.swirlds.gui.model.Reference; import javax.swing.JTextArea; /** @@ -44,8 +45,8 @@ public void prePaint() { || swirldId != null) { // already set this up once return; } - SwirldsPlatform platform = WinBrowser.memberDisplayed.getPlatform(); - swirldId = new Reference(GuiPlatformAccessor.getInstance().getSwirldId(platform.getSelfId())); + Platform platform = WinBrowser.memberDisplayed.getPlatform(); + swirldId = new Reference(GuiModel.getInstance().getSwirldId(platform.getSelfId())); s += "Swirld ID: \n " + swirldId.to62() + "\n"; s += swirldId.toWords(" "); diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/WinTabSwirlds.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/WinTabSwirlds.java index 854a8fdabc96..3ed55b398a3b 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/WinTabSwirlds.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/WinTabSwirlds.java @@ -21,8 +21,11 @@ import static com.swirlds.platform.gui.internal.BrowserWindowManager.getStateHierarchy; import com.swirlds.gui.GuiConstants; -import com.swirlds.gui.InfoEntity; -import com.swirlds.gui.PrePaintableJPanel; +import com.swirlds.gui.components.PrePaintableJPanel; +import com.swirlds.gui.model.InfoApp; +import com.swirlds.gui.model.InfoEntity; +import com.swirlds.gui.model.InfoMember; +import com.swirlds.gui.model.InfoSwirld; import java.awt.Color; import java.awt.Dimension; import java.awt.FlowLayout; diff --git a/platform-sdk/swirlds-platform-gui/build.gradle.kts b/platform-sdk/swirlds-platform-gui/build.gradle.kts index 0b3ea9ded6d3..646cd04486dc 100644 --- a/platform-sdk/swirlds-platform-gui/build.gradle.kts +++ b/platform-sdk/swirlds-platform-gui/build.gradle.kts @@ -24,5 +24,7 @@ plugins { dependencies { api(project(":swirlds-base")) implementation(project(":swirlds-common")) + implementation(project(":swirlds-logging")) implementation(libs.commons.lang3) + compileOnly(libs.spotbugs.annotations) } diff --git a/platform-sdk/swirlds-platform-gui/src/main/java/com/swirlds/gui/GuiUtils.java b/platform-sdk/swirlds-platform-gui/src/main/java/com/swirlds/gui/GuiUtils.java index 639095466e5c..46002f762428 100644 --- a/platform-sdk/swirlds-platform-gui/src/main/java/com/swirlds/gui/GuiUtils.java +++ b/platform-sdk/swirlds-platform-gui/src/main/java/com/swirlds/gui/GuiUtils.java @@ -19,6 +19,8 @@ import com.swirlds.common.Console; import com.swirlds.common.system.SystemExitCode; import com.swirlds.common.system.SystemExitUtils; +import com.swirlds.gui.components.PrePaintableJPanel; +import com.swirlds.gui.components.ScrollableJPanel; import java.awt.Color; import java.awt.Dimension; import java.awt.GraphicsEnvironment; diff --git a/platform-sdk/swirlds-platform-gui/src/main/java/com/swirlds/gui/components/Chart.java b/platform-sdk/swirlds-platform-gui/src/main/java/com/swirlds/gui/components/Chart.java new file mode 100644 index 000000000000..7e3e34e47b4e --- /dev/null +++ b/platform-sdk/swirlds-platform-gui/src/main/java/com/swirlds/gui/components/Chart.java @@ -0,0 +1,364 @@ +/* + * Copyright (C) 2023 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.swirlds.gui.components; + +import static com.swirlds.logging.LogMarker.EXCEPTION; + +import com.swirlds.common.config.BasicConfig; +import com.swirlds.common.metrics.LegacyMetric; +import com.swirlds.common.metrics.Metric; +import com.swirlds.common.metrics.statistics.internal.StatsBuffer; +import edu.umd.cs.findbugs.annotations.NonNull; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.util.Objects; +import javax.swing.JPanel; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +/** a JPanel with one chart that plots a statistic vs. time, either all history or recent */ +public class Chart extends JPanel { + /** for serializing */ + private static final long serialVersionUID = 1L; + + private static final Logger logger = LogManager.getLogger(Chart.class); + + private final Color DARK_GRAY = new Color(0.8f, 0.8f, 0.8f); + + private final Color LIGHT_GRAY = new Color(0.9f, 0.9f, 0.9f); + + private final ChartLabelModel model; + + private final BasicConfig basicConfig; + + /** {@link Metric} of this chart */ + private final transient Metric metric; + /** is this all of history (as opposed to only recent)? */ + private boolean allHistory; + /** the number of labels to generate */ + private long numSteps; + + int stringHeight; + int stringHeightNoDesc; + int minXs; + int maxXs; + int minYs; + int maxYs; + double minXb; + double maxXb; + double minYb; + double maxYb; + + /** + * A chart that displays the history of a statistic from a StatsBuffer + * + * @param width width of the panel in pixels + * @param height height of the panel in pixels + * @param basicConfig + * @param allHistory is this all of history (as opposed to only recent)? + * @param metric {@link Metric} of this chart + */ + public Chart( + @NonNull ChartLabelModel model, + int width, + int height, + @NonNull BasicConfig basicConfig, + boolean allHistory, + final Metric metric) { + this.model = Objects.requireNonNull(model, "model must not be null"); + this.basicConfig = Objects.requireNonNull(basicConfig, "basicConfig must not be null"); + this.setPreferredSize(new Dimension(width, height)); + this.allHistory = allHistory; + this.metric = metric; + this.setBackground(Color.WHITE); + } + + /** + * translate an x value from the buffer to screen coordinates, clipping it to lie inside the chart. + * + * @param x the x parameter from the buffer + * @return the x screen coordinate + */ + private int scaleX(double x) { + if (minXb == maxXb) { // if only one data point, + return (minXs + maxXs) / 2; // then display it in the middle + } + return (int) (Math.min(1, Math.max(0, (x - minXb) / (maxXb - minXb))) * (maxXs - minXs) + minXs); + } + + /** + * translate a y value from the buffer to screen coordinates, clipping it to lie inside the chart. + * + * @param y the y parameter from the buffer + * @return the y screen coordinate + */ + private int scaleY(double y) { + if (minYb == maxYb) { // if a value has been constant throughout history, + return (minYs + maxYs) / 2; // then display it in the middle + } + return (int) (maxYs - Math.min(1, Math.max(0, (y - minYb) / (maxYb - minYb))) * (maxYs - minYs)); + } + + /** + * all x axis labels reflect x values divided by this. This is 1 for seconds, 60 for minutes, etc. + */ + double xDivisor = 1; + /** + * the units for the x axis labels. If "seconds", then xDivisor is 1, if "minutes", then 60, etc. + */ + String xUnits = "seconds"; + + /** + * Check if "step" is a good step size. If so, set numSteps to the number of labels it will generate, and return + * true. Else return false. + * + * @param step the proposed step size + * @param min the minimum value of all the data + * @param max the maximum value of all the data + * @return true if this step size won't produce too many labels + */ + private boolean good(double step, double min, double max) { + if (step <= 0 || max < min) { + return false; + } + numSteps = 1 + Math.round(Math.ceil(max / step) - Math.floor(min / step)); + return 4 <= numSteps && numSteps <= 7; + } + + /** + * Create the y labels and choose their positions + *

+ * This method "returns" xLabel and xLabelVal, by changing those class variables. + */ + private void findYLabel() { + if (maxYb == minYb) { + String s = String.format("%,.0f", minYb); + model.setYLabels(new String[] {s}); + model.setYLabelValues(new double[] {minYb}); + return; + } + double step10 = Math.pow(10, Math.floor(Math.log10(maxYb - minYb)) - 1); + double step = 1; + for (int i = 0; i < 4; i++) { // find a step that results in a good number of labels + if (good(step = step10, minYb, maxYb)) { + break; + } + if (good(step = step10 * 2, minYb, maxYb)) { + break; + } + if (good(step = step10 * 5, minYb, maxYb)) { + break; + } + step10 *= 10; + } + // number of decimal places to show, for the given step (0 if showing an integer is ok) + long decimals = Math.round(Math.max(0, -Math.floor(Math.log10(step)))); + double epsilon = Math.pow(10, -1 - decimals); // if showing 2 decimal places, this is 0.001 + double localMaxYb = Math.ceil(maxYb / step) * step + epsilon; + final String[] yLabel = new String[(int) numSteps - 2]; + final double[] yLabelVal = new double[(int) numSteps - 2]; + for (int i = 0; i < numSteps - 2; i++) { + yLabelVal[i] = localMaxYb - (i + 1) * step + epsilon; + yLabel[i] = String.format("%,." + decimals + "f", yLabelVal[i]); + } + model.setYLabels(yLabel); + model.setYLabelValues(yLabelVal); + } + + /** + * Create the x labels and choose their positions + *

+ * This method "returns" xLabel and xLabelVal, by changing those class variables. + */ + private void findXLabel() { + if (maxXb <= minXb) { + String s = String.format("%,.0f", minXb); + model.setXLabels(new String[] {s}); + model.setXLabelValues(new double[] {minXb}); + return; + } + double step10 = Math.pow(10, Math.floor(Math.log10(maxXb - minXb)) - 1); + double step = 1; + for (int i = 0; i < 4; i++) { // find a step that results in a good number of labels + if (good(step = step10, minXb, maxXb)) { + break; + } + if (good(step = step10 * 2, minXb, maxXb)) { + break; + } + if (good(step = step10 * 5, minXb, maxXb)) { + break; + } + step10 *= 10; + } + if (!good(step, minXb, maxXb)) { + // couldn't find a good step size. Maybe numSteps or the data are NaN? + numSteps = 4; + step = 1; + } + // number of decimal places to show, for the given step (0 if showing an integer is ok) + long decimals = Math.round(Math.max(0, -Math.floor(Math.log10(step)))); + double epsilon = Math.pow(10, -1 - decimals); // if showing 2 decimal places, this is 0.001 + double localMaxXb = Math.ceil(maxXb / step) * step + epsilon; + final String[] xLabel = new String[(int) numSteps - 2]; + final double[] xLabelVal = new double[(int) numSteps - 2]; + for (int i = 0; i < numSteps - 2; i++) { + xLabelVal[i] = localMaxXb - (i + 1) * step + epsilon; + xLabel[i] = String.format("%,." + decimals + "f", xLabelVal[i]); + } + model.setXLabels(xLabel); + model.setXLabelValues(xLabelVal); + } + + @Override + protected void paintComponent(Graphics g) { + super.paintComponent(g); + try { + StatsBuffer buffer; + if (metric instanceof LegacyMetric legacyMetric) { + if (allHistory) { + buffer = legacyMetric.getStatsBuffered().getAllHistory(); + } else { + buffer = legacyMetric.getStatsBuffered().getRecentHistory(); + } + } else { + buffer = new StatsBuffer(0, 0, 0); + } + + minXs = 120; + maxXs = getWidth() - 55; + minYs = 40; + maxYs = getHeight() - 50; + + minXb = buffer.xMin(); + maxXb = buffer.xMax(); + minYb = buffer.yMin(); + maxYb = buffer.yMax(); + + if (maxXb - minXb > 60 * 60 * 24 * 365) { + xDivisor = 60 * 60 * 24 * 365; + xUnits = "years"; + } else if (maxXb - minXb > 60 * 60 * 24) { + xDivisor = 60 * 60 * 24; + xUnits = "days"; + } else if (maxXb - minXb > 60 * 60) { + xDivisor = 60 * 60; + xUnits = "hours"; + } else if (maxXb - minXb > 60 * 1.1) { + xDivisor = 60; + xUnits = "minutes"; + } else { + xDivisor = 1; + xUnits = "seconds"; + } + + g.setColor(Color.BLACK); + stringHeight = g.getFontMetrics().getHeight(); + stringHeightNoDesc = + g.getFontMetrics().getHeight() - g.getFontMetrics().getDescent(); + String title = metric.getName() + " vs. time for " + (allHistory ? "all" : "recent") + " history"; + + if (buffer.numBins() == 0) { + final String s = String.format("Skipping the first %,.0f seconds ...", basicConfig.statsSkipSeconds()); + final int w = g.getFontMetrics().stringWidth(s); + g.drawString(s, (minXs + maxXs - w) / 2, (minYs + maxYs) / 2); + g.drawLine(minXs, maxYs, maxXs, maxYs); // x axis + g.drawLine(minXs, minYs, minXs, maxYs); // y axis + } + for (int i = 0; i < buffer.numBins(); i++) { + g.setColor(LIGHT_GRAY); + int x0, y0, x1, y1; + x0 = scaleX(i == 0 ? buffer.xMin(i) : buffer.xMax(i - 1)); // eliminate gaps + y0 = scaleY(buffer.yMax(i)); + x1 = scaleX(buffer.xMax(i)); + y1 = scaleY(buffer.yMin(i)); + g.fillRect(x0, y0, x1 - x0, y1 - y0); + g.setColor(DARK_GRAY); + x0 = scaleX(i == 0 ? buffer.xMin(i) : buffer.xMax(i - 1)); // eliminate gaps + y0 = scaleY(buffer.yAvg(i) + buffer.yStd(i)); + x1 = scaleX(buffer.xMax(i)); + y1 = scaleY(buffer.yAvg(i) - buffer.yStd(i)); + g.fillRect(x0, y0, x1 - x0, y1 - y0); + g.setColor(Color.BLUE); + if (i > 0) { + x0 = scaleX(buffer.xAvg(i - 1)); + y0 = scaleY(buffer.yAvg(i - 1)); + x1 = scaleX(buffer.xAvg(i)); + y1 = scaleY(buffer.yAvg(i)); + g.drawLine(x0, y0, x1, y1); + } + } + g.setColor(Color.BLACK); + + // draw title and x axis name: + + int w = g.getFontMetrics().stringWidth(title); + g.drawString(title, minXs + (maxXs - minXs - w) / 2, stringHeight); + String s = "Time in the past (in " + xUnits + ")"; + w = g.getFontMetrics().stringWidth(s); + g.drawString(s, minXs + (maxXs - minXs - w) / 2, getHeight() - stringHeight); + + if (buffer.numBins() == 0) { + return; // don't draw labels when there's no data + } + + // draw X axis labels: + + double tt = minXb; + minXb = (minXb - tt) / xDivisor; + maxXb = (maxXb - tt) / xDivisor; + double t2 = (maxXb - minXb) / 50; + minXb -= t2; // make sure the 0 label is displayed + findXLabel(); // labels reflect "time ago", scaled to current units + minXb += t2; + minXb = minXb * xDivisor + tt; + maxXb = maxXb * xDivisor + tt; + + final double[] xLabelVal = new double[model.getXLabelValues().length]; + for (int i = 0; i < model.getXLabelValues().length; i++) { + xLabelVal[i] = model.getXLabelValues()[i] * xDivisor + tt; + } + model.setXLabelValues(xLabelVal); + + for (int i = 0; i < model.getXLabels().length; i++) { + int x = maxXs - (scaleX(model.getXLabelValues()[i]) - minXs); + int stringWidth = g.getFontMetrics().stringWidth(model.getXLabels()[i]); + g.drawLine(x, maxYs + 4, x, maxYs - 4); + g.drawString(model.getXLabels()[i], x - stringWidth / 2 + 1, maxYs + stringHeight + 5); + } + + // draw Y axis labels: + + findYLabel(); + + for (int i = 0; i < model.getYLabels().length; i++) { + int y = scaleY(model.getYLabelValues()[i]); + int stringWidth = g.getFontMetrics().stringWidth(model.getYLabels()[i]); + g.drawLine(minXs - 4, y, minXs + 4, y); + g.drawString(model.getYLabels()[i], minXs - stringWidth - 10, y + stringHeightNoDesc / 2 - 1); + } + + // draw X and Y axes + + g.drawLine(minXs, maxYs, maxXs, maxYs); // x axis + g.drawLine(minXs, minYs, minXs, maxYs); // y axis + } catch (Exception e) { + logger.error(EXCEPTION.getMarker(), "error while painting: {}", e); + } + } +} diff --git a/platform-sdk/swirlds-platform-gui/src/main/java/com/swirlds/gui/components/ChartLabelModel.java b/platform-sdk/swirlds-platform-gui/src/main/java/com/swirlds/gui/components/ChartLabelModel.java new file mode 100644 index 000000000000..80d1d3d392e3 --- /dev/null +++ b/platform-sdk/swirlds-platform-gui/src/main/java/com/swirlds/gui/components/ChartLabelModel.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2023 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.swirlds.gui.components; + +public interface ChartLabelModel { + + void setYLabels(String[] labels); + + void setYLabelValues(double[] values); + + void setXLabels(String[] labels); + + void setXLabelValues(double[] values); + + String[] getYLabels(); + + double[] getYLabelValues(); + + String[] getXLabels(); + + double[] getXLabelValues(); +} diff --git a/platform-sdk/swirlds-platform-gui/src/main/java/com/swirlds/gui/PrePaintableJPanel.java b/platform-sdk/swirlds-platform-gui/src/main/java/com/swirlds/gui/components/PrePaintableJPanel.java similarity index 97% rename from platform-sdk/swirlds-platform-gui/src/main/java/com/swirlds/gui/PrePaintableJPanel.java rename to platform-sdk/swirlds-platform-gui/src/main/java/com/swirlds/gui/components/PrePaintableJPanel.java index 55a2d5c39150..e6e560aea18a 100644 --- a/platform-sdk/swirlds-platform-gui/src/main/java/com/swirlds/gui/PrePaintableJPanel.java +++ b/platform-sdk/swirlds-platform-gui/src/main/java/com/swirlds/gui/components/PrePaintableJPanel.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.swirlds.gui; +package com.swirlds.gui.components; import java.awt.FlowLayout; import java.io.Serial; diff --git a/platform-sdk/swirlds-platform-gui/src/main/java/com/swirlds/gui/ScrollableJPanel.java b/platform-sdk/swirlds-platform-gui/src/main/java/com/swirlds/gui/components/ScrollableJPanel.java similarity index 97% rename from platform-sdk/swirlds-platform-gui/src/main/java/com/swirlds/gui/ScrollableJPanel.java rename to platform-sdk/swirlds-platform-gui/src/main/java/com/swirlds/gui/components/ScrollableJPanel.java index a097ea3b5c0f..95c761479680 100644 --- a/platform-sdk/swirlds-platform-gui/src/main/java/com/swirlds/gui/ScrollableJPanel.java +++ b/platform-sdk/swirlds-platform-gui/src/main/java/com/swirlds/gui/components/ScrollableJPanel.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.swirlds.gui; +package com.swirlds.gui.components; import javax.swing.JScrollPane; diff --git a/platform-sdk/swirlds-platform-gui/src/main/java/com/swirlds/gui/model/GuiModel.java b/platform-sdk/swirlds-platform-gui/src/main/java/com/swirlds/gui/model/GuiModel.java new file mode 100644 index 000000000000..a2d37c023fbc --- /dev/null +++ b/platform-sdk/swirlds-platform-gui/src/main/java/com/swirlds/gui/model/GuiModel.java @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2023 Hedera Hashgraph, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.swirlds.gui.model; + +import com.swirlds.common.system.NodeId; +import edu.umd.cs.findbugs.annotations.NonNull; +import edu.umd.cs.findbugs.annotations.Nullable; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; + +/** + * Extraction of several params from {@code GuiPlatformAccessor} to move it to new gui module. + */ +@Deprecated(forRemoval = true) +public class GuiModel { + + private static final GuiModel INSTANCE = new GuiModel(); + private final Map aboutStrings = new ConcurrentHashMap<>(); + private final Map platformNames = new ConcurrentHashMap<>(); + private final Map swirldIds = new ConcurrentHashMap<>(); + private final Map instanceNumbers = new ConcurrentHashMap<>(); + + private GuiModel() {} + + /** + * The SwirldMain calls this to set the string that is shown when the user chooses "About" from the Swirlds menu in + * the upper-right corner of the window. It is recommended that this be a short string that includes the name of the + * app, the version number, and the year. + * + * @param nodeId the ID of the node + * @param about wha should show in the "about" window from the menu + */ + public void setAbout(@NonNull final NodeId nodeId, @NonNull final String about) { + Objects.requireNonNull(nodeId, "nodeId must not be null"); + Objects.requireNonNull(about, "about must not be null"); + aboutStrings.put(nodeId, about); + } + + /** + * Get the "about" string, or an empty string if none has been set. + * + * @param nodeId the ID of the node + * @return an "about" string + */ + public String getAbout(@NonNull final NodeId nodeId) { + Objects.requireNonNull(nodeId, "nodeId must not be null"); + return aboutStrings.getOrDefault(nodeId, ""); + } + + /** + * Set a platform name, given the node ID. + * + * @param nodeId the ID of the node + * @param platformName a platform name + */ + public void setPlatformName(@NonNull final NodeId nodeId, @NonNull final String platformName) { + Objects.requireNonNull(nodeId, "nodeId must not be null"); + Objects.requireNonNull(platformName, "platformName must not be null"); + platformNames.put(nodeId, platformName); + } + + /** + * Get a platform name, given the node ID, or an empty string if none has been set. + * + * @param nodeId the ID of the node + * @return a platform name + */ + @NonNull + public String getPlatformName(@NonNull final NodeId nodeId) { + Objects.requireNonNull(nodeId, "nodeId must not be null"); + return platformNames.getOrDefault(nodeId, ""); + } + + /** + * Set the swirld ID for a node. + * + * @param nodeId the ID of the node + * @param swirldId the swirld ID + */ + public void setSwirldId(@NonNull final NodeId nodeId, @NonNull final byte[] swirldId) { + Objects.requireNonNull(nodeId, "nodeId must not be null"); + Objects.requireNonNull(swirldId, "swirldId must not be null"); + swirldIds.put(nodeId, swirldId); + } + + /** + * Get the swirld ID for a node, or null if none is set. + * + * @param nodeId the ID of the node + * @return the swirld ID + */ + @Nullable + public byte[] getSwirldId(@NonNull final NodeId nodeId) { + Objects.requireNonNull(nodeId, "nodeId must not be null"); + return swirldIds.getOrDefault(nodeId, null); + } + + /** + * Set the instance number for a node. + * + * @param nodeId the ID of the node + * @param instanceNumber the instance number + */ + public void setInstanceNumber(@NonNull final NodeId nodeId, final int instanceNumber) { + Objects.requireNonNull(nodeId, "nodeId must not be null"); + instanceNumbers.put(nodeId, instanceNumber); + } + + /** + * Get the instance number for a node, or -1 if none is set. + * + * @param nodeId the ID of the node + * @return the instance number + */ + public int getInstanceNumber(@NonNull final NodeId nodeId) { + Objects.requireNonNull(nodeId, "nodeId must not be null"); + return instanceNumbers.getOrDefault(nodeId, -1); + } + + public static GuiModel getInstance() { + return INSTANCE; + } +} diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/InfoApp.java b/platform-sdk/swirlds-platform-gui/src/main/java/com/swirlds/gui/model/InfoApp.java similarity index 87% rename from platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/InfoApp.java rename to platform-sdk/swirlds-platform-gui/src/main/java/com/swirlds/gui/model/InfoApp.java index 77e6a92b585b..3f2c8179968a 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/InfoApp.java +++ b/platform-sdk/swirlds-platform-gui/src/main/java/com/swirlds/gui/model/InfoApp.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018-2023 Hedera Hashgraph, LLC + * Copyright (C) 2023 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,9 +14,8 @@ * limitations under the License. */ -package com.swirlds.platform.gui.internal; +package com.swirlds.gui.model; -import com.swirlds.gui.InfoEntity; import java.util.ArrayList; import java.util.List; diff --git a/platform-sdk/swirlds-platform-gui/src/main/java/com/swirlds/gui/InfoEntity.java b/platform-sdk/swirlds-platform-gui/src/main/java/com/swirlds/gui/model/InfoEntity.java similarity index 97% rename from platform-sdk/swirlds-platform-gui/src/main/java/com/swirlds/gui/InfoEntity.java rename to platform-sdk/swirlds-platform-gui/src/main/java/com/swirlds/gui/model/InfoEntity.java index f9dddb438b9b..956528cb71da 100644 --- a/platform-sdk/swirlds-platform-gui/src/main/java/com/swirlds/gui/InfoEntity.java +++ b/platform-sdk/swirlds-platform-gui/src/main/java/com/swirlds/gui/model/InfoEntity.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.swirlds.gui; +package com.swirlds.gui.model; import javax.swing.JPanel; diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/InfoMember.java b/platform-sdk/swirlds-platform-gui/src/main/java/com/swirlds/gui/model/InfoMember.java similarity index 76% rename from platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/InfoMember.java rename to platform-sdk/swirlds-platform-gui/src/main/java/com/swirlds/gui/model/InfoMember.java index 65b2b175d2c8..a960664f087a 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/InfoMember.java +++ b/platform-sdk/swirlds-platform-gui/src/main/java/com/swirlds/gui/model/InfoMember.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022-2023 Hedera Hashgraph, LLC + * Copyright (C) 2023 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,10 +14,9 @@ * limitations under the License. */ -package com.swirlds.platform.gui.internal; +package com.swirlds.gui.model; -import com.swirlds.gui.InfoEntity; -import com.swirlds.platform.SwirldsPlatform; +import com.swirlds.common.system.Platform; import java.util.ArrayList; import java.util.List; @@ -28,9 +27,9 @@ public class InfoMember extends InfoEntity { private final List states = new ArrayList<>(); // children - private final SwirldsPlatform platform; + private final Platform platform; - public InfoMember(final InfoSwirld swirld, final SwirldsPlatform platform) { + public InfoMember(final InfoSwirld swirld, final Platform platform) { super(platform.getSelfAddress().getNickname() + " - " + platform.getSelfAddress().getSelfName()); this.platform = platform; @@ -41,7 +40,7 @@ public List getStates() { return states; } - public SwirldsPlatform getPlatform() { + public Platform getPlatform() { return platform; } } diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/InfoState.java b/platform-sdk/swirlds-platform-gui/src/main/java/com/swirlds/gui/model/InfoState.java similarity index 86% rename from platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/InfoState.java rename to platform-sdk/swirlds-platform-gui/src/main/java/com/swirlds/gui/model/InfoState.java index b8c50f255722..7b70c8515dfd 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/InfoState.java +++ b/platform-sdk/swirlds-platform-gui/src/main/java/com/swirlds/gui/model/InfoState.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016-2023 Hedera Hashgraph, LLC + * Copyright (C) 2023 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,9 +14,7 @@ * limitations under the License. */ -package com.swirlds.platform.gui.internal; - -import com.swirlds.gui.InfoEntity; +package com.swirlds.gui.model; /** * Metadata about a state stored by a member in a swirld running on an app. diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/InfoSwirld.java b/platform-sdk/swirlds-platform-gui/src/main/java/com/swirlds/gui/model/InfoSwirld.java similarity index 90% rename from platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/InfoSwirld.java rename to platform-sdk/swirlds-platform-gui/src/main/java/com/swirlds/gui/model/InfoSwirld.java index 2e4276d64add..b41659680ae6 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/InfoSwirld.java +++ b/platform-sdk/swirlds-platform-gui/src/main/java/com/swirlds/gui/model/InfoSwirld.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022-2023 Hedera Hashgraph, LLC + * Copyright (C) 2023 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,9 +14,8 @@ * limitations under the License. */ -package com.swirlds.platform.gui.internal; +package com.swirlds.gui.model; -import com.swirlds.gui.InfoEntity; import java.util.ArrayList; import java.util.List; diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/Reference.java b/platform-sdk/swirlds-platform-gui/src/main/java/com/swirlds/gui/model/Reference.java similarity index 99% rename from platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/Reference.java rename to platform-sdk/swirlds-platform-gui/src/main/java/com/swirlds/gui/model/Reference.java index 57e600c39e27..32f5601b4bfe 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/Reference.java +++ b/platform-sdk/swirlds-platform-gui/src/main/java/com/swirlds/gui/model/Reference.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016-2023 Hedera Hashgraph, LLC + * Copyright (C) 2023 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.swirlds.platform.gui.internal; +package com.swirlds.gui.model; import static com.swirlds.logging.LogMarker.EXCEPTION; diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/WordList.java b/platform-sdk/swirlds-platform-gui/src/main/java/com/swirlds/gui/model/WordList.java similarity index 99% rename from platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/WordList.java rename to platform-sdk/swirlds-platform-gui/src/main/java/com/swirlds/gui/model/WordList.java index d09508674a73..bcc6e988232b 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/gui/internal/WordList.java +++ b/platform-sdk/swirlds-platform-gui/src/main/java/com/swirlds/gui/model/WordList.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016-2023 Hedera Hashgraph, LLC + * Copyright (C) 2023 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.swirlds.platform.gui.internal; +package com.swirlds.gui.model; import java.util.Arrays; import java.util.List; @@ -26,9 +26,9 @@ * * These are 2048 English words, no two of which have the same first 4 letters. */ -class WordList { +public class WordList { /** the list of 2048 words */ - static List words = Arrays.asList( + public static List words = Arrays.asList( "abandon", "ability", "able", diff --git a/platform-sdk/swirlds-platform-gui/src/main/java/module-info.java b/platform-sdk/swirlds-platform-gui/src/main/java/module-info.java index 3132894845c6..8ae885ceb26f 100644 --- a/platform-sdk/swirlds-platform-gui/src/main/java/module-info.java +++ b/platform-sdk/swirlds-platform-gui/src/main/java/module-info.java @@ -1,8 +1,13 @@ module com.swirlds.gui { exports com.swirlds.gui; exports com.swirlds.gui.hashgraph; + exports com.swirlds.gui.components; + exports com.swirlds.gui.model; requires transitive java.desktop; requires org.apache.commons.lang3; requires com.swirlds.common; + requires static com.github.spotbugs.annotations; + requires com.swirlds.logging; + requires org.apache.logging.log4j; }