diff --git a/libs/derbyshared.jar b/libs/derbyshared.jar
new file mode 100644
index 0000000..ca71ed0
Binary files /dev/null and b/libs/derbyshared.jar differ
diff --git a/libs/derbytools.jar b/libs/derbytools.jar
new file mode 100644
index 0000000..cf104e5
Binary files /dev/null and b/libs/derbytools.jar differ
diff --git a/src/jdiskmark/AdvancedOptionsFrame.form b/src/jdiskmark/AdvancedOptionsFrame.form
new file mode 100644
index 0000000..6e6412c
--- /dev/null
+++ b/src/jdiskmark/AdvancedOptionsFrame.form
@@ -0,0 +1,85 @@
+
+
+
diff --git a/src/jdiskmark/AdvancedOptionsFrame.java b/src/jdiskmark/AdvancedOptionsFrame.java
new file mode 100644
index 0000000..5274b41
--- /dev/null
+++ b/src/jdiskmark/AdvancedOptionsFrame.java
@@ -0,0 +1,112 @@
+
+package jdiskmark;
+
+import javax.swing.DefaultComboBoxModel;
+import javax.swing.JButton;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+
+/**
+ *
+ * @author james
+ */
+public class AdvancedOptionsFrame extends javax.swing.JFrame {
+
+ /**
+ * Creates new form AdvancedOptionsFrame
+ */
+ @SuppressWarnings("unchecked")
+ public AdvancedOptionsFrame() {
+ getContentPane().setLayout(new java.awt.BorderLayout());
+ initComponents();
+
+ // --- Existing combo setup ---
+ setLocationRelativeTo(Gui.mainFrame);
+ DefaultComboBoxModel rModeModel =
+ new DefaultComboBoxModel<>(RenderFrequencyMode.values());
+ renderModeCombo.setModel(rModeModel);
+ }
+
+
+
+ /**
+ * This method is called from within the constructor to initialize the form.
+ * WARNING: Do NOT modify this code. The content of this method is always
+ * regenerated by the Form Editor.
+ */
+ @SuppressWarnings("unchecked")
+ // //GEN-BEGIN:initComponents
+ private void initComponents() {
+
+ jLabel1 = new javax.swing.JLabel();
+ renderModeCombo = new javax.swing.JComboBox();
+ jButton1 = new javax.swing.JButton();
+
+ setTitle("Advanced Options");
+
+ jLabel1.setText("Render Mode");
+
+ renderModeCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "" }));
+ renderModeCombo.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ renderModeComboActionPerformed(evt);
+ }
+ });
+
+ jButton1.setLabel("Close");
+ jButton1.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ closeButtonActionPerformed(evt);
+ }
+ });
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
+ getContentPane().setLayout(layout);
+ layout.setHorizontalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addComponent(jLabel1)
+ .addGap(18, 18, 18)
+ .addComponent(renderModeCombo, javax.swing.GroupLayout.PREFERRED_SIZE, 128, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addContainerGap(177, Short.MAX_VALUE))
+ .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
+ .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(jButton1)
+ .addGap(26, 26, 26))
+ );
+ layout.setVerticalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(jLabel1)
+ .addComponent(renderModeCombo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 227, Short.MAX_VALUE)
+ .addComponent(jButton1)
+ .addGap(18, 18, 18))
+ );
+
+ pack();
+ }// //GEN-END:initComponents
+
+ private void renderModeComboActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_renderModeComboActionPerformed
+ try {
+ App.rmOption = (RenderFrequencyMode) renderModeCombo.getSelectedItem();
+ } catch (RuntimeException re) {
+ System.err.print(" error casting item object" + re.getMessage());
+ }
+ }//GEN-LAST:event_renderModeComboActionPerformed
+
+ private void closeButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_closeButtonActionPerformed
+ setVisible(false);
+ }//GEN-LAST:event_closeButtonActionPerformed
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JButton jButton1;
+ private javax.swing.JLabel jLabel1;
+ private javax.swing.JComboBox renderModeCombo;
+ // End of variables declaration//GEN-END:variables
+
+}
diff --git a/src/jdiskmark/App.java b/src/jdiskmark/App.java
index ddfb7e1..c681aa8 100644
--- a/src/jdiskmark/App.java
+++ b/src/jdiskmark/App.java
@@ -68,6 +68,9 @@ public static enum State { IDLE_STATE, DISK_TEST_STATE };
public static int blockSizeKb = 512; // size of a block in KBs
public static int numOfThreads = 1; // number of threads
+ // advanced options
+ public static RenderFrequencyMode rmOption = RenderFrequencyMode.PER_SAMPLE;
+
public static BenchmarkWorker worker = null;
public static int nextSampleNumber = 1; // number of the next sample
public static double wMax = -1, wMin = -1, wAvg = -1, wAcc = -1;
@@ -156,6 +159,7 @@ public static void init() {
Gui.mainFrame = new MainFrame();
Gui.runPanel.hideFirstColumn();
Gui.selFrame = new SelectDriveFrame();
+ Gui.advancedFrame = new AdvancedOptionsFrame();
System.out.println(App.getConfigString());
Gui.mainFrame.loadConfig();
Gui.mainFrame.setLocationRelativeTo(null);
@@ -250,7 +254,11 @@ public static void loadConfig() {
value = p.getProperty("palette", String.valueOf(Gui.palette));
Gui.palette = Gui.Palette.valueOf(value);
- }
+
+ value = p.getProperty("renderMode", String.valueOf(rmOption));
+ rmOption = RenderFrequencyMode.valueOf(value.toUpperCase());
+
+ }
public static void saveConfig() {
if (p == null) { p = new Properties(); }
@@ -269,6 +277,7 @@ public static void saveConfig() {
p.setProperty("numOfThreads", String.valueOf(numOfThreads));
p.setProperty("writeSyncEnable", String.valueOf(writeSyncEnable));
p.setProperty("palette", Gui.palette.name());
+ p.setProperty("renderMode", rmOption.name());
// write properties file
try {
diff --git a/src/jdiskmark/Benchmark.java b/src/jdiskmark/Benchmark.java
index 7ede76f..9701c5f 100644
--- a/src/jdiskmark/Benchmark.java
+++ b/src/jdiskmark/Benchmark.java
@@ -20,6 +20,8 @@
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
+import jakarta.persistence.Enumerated;
+import jakarta.persistence.EnumType;
/**
* A read or write benchmark
@@ -80,6 +82,10 @@ public enum BenchmarkType {
// benchmark parameters
@Column
BenchmarkType benchmarkType;
+
+ @Enumerated(EnumType.STRING)
+ @Column
+ private RenderFrequencyMode renderMode = RenderFrequencyMode.PER_SAMPLE;
// timestamps
@Convert(converter = LocalDateTimeAttributeConverter.class)
@@ -129,6 +135,15 @@ public Long getId() {
public void setId(Long id) {
this.id = id;
}
+
+ public RenderFrequencyMode getRenderMode() {
+ return renderMode != null ? renderMode : RenderFrequencyMode.PER_SAMPLE;
+ }
+
+ public void setRenderMode(RenderFrequencyMode renderMode) {
+ this.renderMode = renderMode;
+ }
+
public String getDriveInfo() {
return driveModel + " - " + partitionId + ": " + getUsageTitleDisplay();
}
@@ -138,7 +153,7 @@ public String getUsageTitleDisplay() {
public String getUsageColumnDisplay() {
return percentUsed + "%";
}
-
+
public String getStartTimeString() {
return startTime.format(DATE_FORMAT);
}
diff --git a/src/jdiskmark/BenchmarkOperation.java b/src/jdiskmark/BenchmarkOperation.java
index 11a87d8..9fb1616 100644
--- a/src/jdiskmark/BenchmarkOperation.java
+++ b/src/jdiskmark/BenchmarkOperation.java
@@ -21,6 +21,9 @@
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
+import jakarta.persistence.Enumerated;
+import jakarta.persistence.EnumType;
+
/**
* A read or write benchmark
@@ -229,6 +232,18 @@ public void setIops(long iops) {
this.iops = iops;
}
+// @Enumerated(EnumType.STRING)
+// @Column
+// private RenderFrequencyMode renderMode;
+
+// public void setRenderMode(RenderFrequencyMode renderMode) {
+// this.renderMode = renderMode;
+// }
+
+// public RenderFrequencyMode getRenderMode() {
+// // Gracefully default to PER_SAMPLE if null or missing
+// return renderMode != null ? renderMode : RenderFrequencyMode.PER_SAMPLE;
+// }
// utility methods for collection
static List findAll() {
diff --git a/src/jdiskmark/BenchmarkPanel.java b/src/jdiskmark/BenchmarkPanel.java
index efc634e..a24b791 100644
--- a/src/jdiskmark/BenchmarkPanel.java
+++ b/src/jdiskmark/BenchmarkPanel.java
@@ -17,6 +17,10 @@ public class BenchmarkPanel extends javax.swing.JPanel {
public BenchmarkPanel() {
initComponents();
Gui.runPanel = BenchmarkPanel.this;
+
+ // Dynamically add Render Mode column
+ DefaultTableModel model = (DefaultTableModel) runTable.getModel();
+ model.addColumn("Render Mode");
// Tooltip only – keep it simple
runTable.setToolTipText("Mode: Write* means Write Sync was enabled");
@@ -123,7 +127,6 @@ public boolean isCellEditable(int rowIndex, int columnIndex) {
public void addRun(Benchmark run) {
-
List operations = run.getOperations();
DefaultTableModel model = (DefaultTableModel) this.runTable.getModel();
for (BenchmarkOperation o : operations) {
@@ -142,6 +145,7 @@ public void addRun(Benchmark run) {
o.getAccTimeDisplay(),
o.getBwMinMaxDisplay(),
o.getBwAvgDisplay(),
+ (o.getRenderMode() != null ? o.getRenderMode().toString() : "-")
});
}
}
diff --git a/src/jdiskmark/BenchmarkWorker.java b/src/jdiskmark/BenchmarkWorker.java
index 0de34b9..086482a 100644
--- a/src/jdiskmark/BenchmarkWorker.java
+++ b/src/jdiskmark/BenchmarkWorker.java
@@ -25,11 +25,19 @@
import static jdiskmark.App.locationDir;
import static jdiskmark.App.numOfSamples;
+
/**
* Thread running the disk benchmarking. only one of these threads can run at
* once.
*/
public class BenchmarkWorker extends SwingWorker {
+
+ // Temporary buffer for timed render modes (100/500/1000 ms)
+ private final List intervalBuffer = new ArrayList<>();
+ private long lastPublishTime = System.currentTimeMillis();
+ private long nextPublishTime = lastPublishTime;
+
+
public static int[][] divideIntoRanges(int startIndex, int endIndex, int numThreads) {
if (numThreads <= 0 || endIndex < startIndex) {
@@ -83,6 +91,8 @@ protected Boolean doInBackground() throws Exception {
}
Gui.updateLegendAndAxis();
+
+
if (App.autoReset == true) {
App.resetTestData();
@@ -109,6 +119,8 @@ protected Boolean doInBackground() throws Exception {
List> futures = new ArrayList<>();
Benchmark benchmark = new Benchmark(App.benchmarkType);
+ benchmark.setRenderMode(App.rmOption);
+ RenderFrequencyMode renderMode = benchmark.getRenderMode();
// system info
benchmark.processorName = App.processorName;
@@ -130,7 +142,7 @@ protected Boolean doInBackground() throws Exception {
wOperation.ioMode = BenchmarkOperation.IOMode.WRITE;
wOperation.blockOrder = App.blockSequence;
wOperation.numSamples = App.numOfSamples;
- wOperation.numBlocks = App.numOfSamples;
+ wOperation.numBlocks = App.numOfBlocks;
wOperation.blockSize = App.blockSizeKb;
wOperation.txSize = App.targetTxSizeKb();
wOperation.numThreads = App.numOfThreads;
@@ -141,6 +153,17 @@ protected Boolean doInBackground() throws Exception {
if (App.multiFile == false) {
testFile = new File(dataDir.getAbsolutePath() + File.separator + "testdata.jdm");
}
+
+ if (renderMode == RenderFrequencyMode.PER_100MS
+ || renderMode == RenderFrequencyMode.PER_500MS
+ || renderMode == RenderFrequencyMode.PER_1000MS) {
+ synchronized (intervalBuffer) {
+ intervalBuffer.clear();
+ }
+ long now = System.currentTimeMillis();
+ lastPublishTime = now;
+ nextPublishTime = now + renderMode.getIntervalMillis();
+ }
// GH-20 instantiate threads to operate on each range
ExecutorService executorService = Executors.newFixedThreadPool(App.numOfThreads);
@@ -156,11 +179,11 @@ protected Boolean doInBackground() throws Exception {
if (App.multiFile == true) {
testFile = new File(dataDir.getAbsolutePath()
+ File.separator + "testdata" + s + ".jdm");
- }
+ }
Sample sample = new Sample(WRITE, s);
long startTime = System.nanoTime();
long totalBytesWrittenInSample = 0;
- String mode = (App.writeSyncEnable) ? "rwd" : "rw";
+ String mode = (App.writeSyncEnable) ? "rwd" : "rw";
try {
try (RandomAccessFile rAccFile = new RandomAccessFile(testFile, mode)) {
@@ -193,20 +216,64 @@ protected Boolean doInBackground() throws Exception {
// msg("s:" + s + " write IO is " + sample.getBwMbSecDisplay() + " MB/s "
// + "(" + Util.displayString(mbWritten) + "MB written in "
// + Util.displayString(sec) + " sec) elapsedNs: " + elapsedTimeNs);
- App.updateMetrics(sample);
- publish(sample);
-
- wOperation.bwMax = sample.cumMax;
- wOperation.bwMin = sample.cumMin;
- wOperation.bwAvg = sample.cumAvg;
- wOperation.accAvg = sample.cumAccTimeMs;
- wOperation.add(sample);
+ // Determine when to publish based on render mode
+
+ switch (renderMode) {
+ case PER_SAMPLE -> {
+ App.updateMetrics(sample);
+ publish(sample);
+ wOperation.add(sample);
+ }
+ case PER_OPERATION -> {
+ wOperation.add(sample);
+ }
+ case PER_100MS, PER_500MS, PER_1000MS -> {
+ long interval = renderMode.getIntervalMillis();
+ long now = System.currentTimeMillis();
+
+ // collect samples into buffer
+ synchronized (intervalBuffer) {
+ intervalBuffer.add(sample);
+ }
+
+ // check if it’s time to flush
+ if (now >= nextPublishTime) {
+ synchronized (intervalBuffer) {
+ for (Sample sm : intervalBuffer) {
+ App.updateMetrics(sm);
+ publish(sm);
+ }
+ intervalBuffer.clear();
+ nextPublishTime = now + interval;
+ }
+ lastPublishTime = now;
+ }
+
+ wOperation.add(sample);
+ }
+
+ }
}
}));
}
executorService.shutdown();
executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
+
+ if (!wOperation.getSamples().isEmpty()) {
+ Sample last = wOperation.getSamples().get(wOperation.getSamples().size() - 1);
+ wOperation.bwMax = last.cumMax;
+ wOperation.bwMin = last.cumMin;
+ wOperation.bwAvg = last.cumAvg;
+ wOperation.accAvg = last.cumAccTimeMs;
+ }
+
+ if (renderMode == RenderFrequencyMode.PER_OPERATION) {
+ for (Sample s : wOperation.getSamples()) {
+ App.updateMetrics(s);
+ publish(s);
+ }
+ }
// GH-10 file IOPS processing
wOperation.endTime = LocalDateTime.now();
@@ -224,7 +291,7 @@ protected Boolean doInBackground() throws Exception {
BenchmarkOperation rOperation = new BenchmarkOperation();
rOperation.setBenchmark(benchmark);
// operation parameters
- rOperation.ioMode = BenchmarkOperation.IOMode.READ;
+ rOperation.ioMode = BenchmarkOperation.IOMode.READ;
rOperation.blockOrder = App.blockSequence;
rOperation.numSamples = App.numOfSamples;
rOperation.numBlocks = App.numOfBlocks;
@@ -283,20 +350,60 @@ protected Boolean doInBackground() throws Exception {
// msg("s:" + s + " read IO is " + sample.getBwMbSecDisplay() + " MB/s "
// + "(" + Util.displayString(mbRead) + "MB read in "
// + Util.displayString(sec) + " sec) elapsedNs: " + elapsedTimeNs);
- App.updateMetrics(sample);
- publish(sample);
- rOperation.bwMax = sample.cumMax;
- rOperation.bwMin = sample.cumMin;
- rOperation.bwAvg = sample.cumAvg;
- rOperation.accAvg = sample.cumAccTimeMs;
- rOperation.add(sample);
+ switch (renderMode) {
+ case PER_SAMPLE -> {
+ App.updateMetrics(sample);
+ publish(sample);
+ rOperation.add(sample);
+ }
+ case PER_OPERATION -> {
+ rOperation.add(sample);
+ }
+ case PER_100MS, PER_500MS, PER_1000MS -> {
+ long interval = renderMode.getIntervalMillis();
+ long now = System.currentTimeMillis();
+
+ synchronized (intervalBuffer) {
+ intervalBuffer.add(sample);
+ }
+
+ if (now >= nextPublishTime) {
+ synchronized (intervalBuffer) {
+ for (Sample sm : intervalBuffer) {
+ App.updateMetrics(sm);
+ publish(sm);
+ }
+ intervalBuffer.clear();
+ nextPublishTime = now + interval;
+ }
+ lastPublishTime = now;
+ }
+
+ rOperation.add(sample);
+ }
+ }
+
+ if (!rOperation.getSamples().isEmpty()) {
+ Sample last = rOperation.getSamples().get(rOperation.getSamples().size() - 1);
+ rOperation.bwMax = last.cumMax;
+ rOperation.bwMin = last.cumMin;
+ rOperation.bwAvg = last.cumAvg;
+ rOperation.accAvg = last.cumAccTimeMs;
+ }
}
}));
- }
+ }
executorService.shutdown();
executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
+ if (renderMode == RenderFrequencyMode.PER_OPERATION) {
+ for (Sample s : rOperation.getSamples()) {
+ App.updateMetrics(s);
+ publish(s);
+ }
+ }
+
// GH-10 file IOPS processing
rOperation.endTime = LocalDateTime.now();
rOperation.setTotalOps(rUnitsComplete[0]);
diff --git a/src/jdiskmark/Gui.java b/src/jdiskmark/Gui.java
index 081b599..e8299ba 100644
--- a/src/jdiskmark/Gui.java
+++ b/src/jdiskmark/Gui.java
@@ -12,6 +12,8 @@
import java.util.ArrayList;
import javax.swing.JOptionPane;
import javax.swing.JProgressBar;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
import org.jfree.chart.ChartMouseEvent;
import org.jfree.chart.ChartMouseListener;
import javax.swing.UIManager;
@@ -26,6 +28,8 @@
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import org.jfree.ui.RectangleInsets;
+import jdiskmark.App;
+
/**
* Store GUI references for easy access
@@ -35,8 +39,20 @@ public final class Gui {
public static enum Palette { CLASSIC, BLUE_GREEN, BARD_COOL, BARD_WARM };
public static Palette palette = Palette.CLASSIC;
+ private static jdiskmark.RenderFrequencyMode renderFrequencyMode = jdiskmark.RenderFrequencyMode.PER_SAMPLE;
+
+ public static RenderFrequencyMode getRenderFrequencyMode() {
+ return renderFrequencyMode;
+ }
+
+ public static void setRenderFrequencyMode(RenderFrequencyMode mode) {
+ renderFrequencyMode = mode;
+ }
+
public static ChartPanel chartPanel = null;
+ public static JLabel renderModeLabel = new JLabel("Render Mode: PER_SAMPLE");
public static MainFrame mainFrame = null;
+ public static AdvancedOptionsFrame advancedFrame = null;
public static SelectDriveFrame selFrame = null;
public static XYSeries wSeries, wAvgSeries, wMaxSeries, wMinSeries, wDrvAccess;
public static XYSeries rSeries, rAvgSeries, rMaxSeries, rMinSeries, rDrvAccess;
@@ -87,7 +103,29 @@ public static void configureLaf() {
}
}
- public static ChartPanel createChartPanel() {
+ public static void updateRenderView() {
+ RenderFrequencyMode mode = Gui.mainFrame.getRenderMode();
+
+ boolean showChart = true; // all modes show chart in this example
+ boolean showTable = (mode == RenderFrequencyMode.PER_100MS ||
+ mode == RenderFrequencyMode.PER_500MS ||
+ mode == RenderFrequencyMode.PER_1000MS);
+
+ if (chartPanel != null) {
+ chartPanel.setVisible(showChart);
+ }
+
+ Gui.mainFrame.setTableVisible(showTable);
+
+ }
+
+ public static void refreshRenderLabel() {
+ if (renderModeLabel != null) {
+ renderModeLabel.setText("Render Mode: " + getRenderFrequencyMode());
+ }
+ }
+
+ public static JPanel createChartPanel() {
wSeries = new XYSeries("Write");
wAvgSeries = new XYSeries("Write Avg");
@@ -175,12 +213,9 @@ public static ChartPanel createChartPanel() {
chart = new JFreeChart("", null , plot, true);
- // correct the parenthesis from being below vertical centering
chart.getTitle().setFont(new Font("Verdana", Font.BOLD, 17));
chartPanel = new ChartPanel(chart) {
- // Only way to set the size of chart panel
- // ref: http://www.jfree.org/phpBB2/viewtopic.php?p=75516
@Override
public Dimension getPreferredSize() {
return new Dimension(500, 325);
@@ -209,10 +244,35 @@ public void chartMouseMoved(ChartMouseEvent cme) {
// no action
}
});
- updateLegendAndAxis();
- return chartPanel;
- }
-
+ updateLegendAndAxis();
+
+ // Creates a wrapper panel with vertical layout
+ JPanel wrapperPanel = new JPanel(new java.awt.BorderLayout());
+
+ // Creates a small left-aligned panel for the label
+ JPanel topPanel = new JPanel(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT, 5, 2));
+ topPanel.setOpaque(false);
+
+ // Render Mode label
+ renderModeLabel = new JLabel("Render Mode: " + Gui.getRenderFrequencyMode());
+ renderModeLabel.setFont(new Font("Verdana", Font.BOLD, 10));
+ renderModeLabel.setForeground(Color.BLACK);
+
+ // Add subtle light-gray background with slight transparency
+ renderModeLabel.setOpaque(true);
+ renderModeLabel.setBackground(new Color(240, 240, 240, 200)); // light gray w/ transparency
+ renderModeLabel.setBorder(javax.swing.BorderFactory.createEmptyBorder(2, 6, 2, 6)); // padding
+
+ // Add label to top panel
+ topPanel.add(renderModeLabel);
+
+ // Add top panel and chart panel to wrapper
+ wrapperPanel.add(topPanel, java.awt.BorderLayout.NORTH);
+ wrapperPanel.add(chartPanel, java.awt.BorderLayout.CENTER);
+
+ return wrapperPanel;
+ }
+
public static void addWriteSample(Sample s) {
wSeries.add(s.sampleNum, s.bwMbSec);
wAvgSeries.add(s.sampleNum, s.cumAvg);
diff --git a/src/jdiskmark/MainFrame.form b/src/jdiskmark/MainFrame.form
index d41a566..25c824b 100644
--- a/src/jdiskmark/MainFrame.form
+++ b/src/jdiskmark/MainFrame.form
@@ -196,6 +196,16 @@
+
+