summaryrefslogtreecommitdiffstats
path: root/watchmaker/swing/src/java/main/org/uncommons/watchmaker/swing/evolutionmonitor/StatusBar.java
diff options
context:
space:
mode:
Diffstat (limited to 'watchmaker/swing/src/java/main/org/uncommons/watchmaker/swing/evolutionmonitor/StatusBar.java')
-rw-r--r--watchmaker/swing/src/java/main/org/uncommons/watchmaker/swing/evolutionmonitor/StatusBar.java165
1 files changed, 165 insertions, 0 deletions
diff --git a/watchmaker/swing/src/java/main/org/uncommons/watchmaker/swing/evolutionmonitor/StatusBar.java b/watchmaker/swing/src/java/main/org/uncommons/watchmaker/swing/evolutionmonitor/StatusBar.java
new file mode 100644
index 0000000..51c6651
--- /dev/null
+++ b/watchmaker/swing/src/java/main/org/uncommons/watchmaker/swing/evolutionmonitor/StatusBar.java
@@ -0,0 +1,165 @@
+//=============================================================================
+// Copyright 2006-2010 Daniel W. Dyer
+//
+// 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 org.uncommons.watchmaker.swing.evolutionmonitor;
+
+import java.util.concurrent.atomic.AtomicInteger;
+import javax.swing.BorderFactory;
+import javax.swing.Box;
+import javax.swing.BoxLayout;
+import javax.swing.JLabel;
+import javax.swing.SwingUtilities;
+import org.uncommons.watchmaker.framework.PopulationData;
+import org.uncommons.watchmaker.framework.islands.IslandEvolutionObserver;
+
+/**
+ * Status bar component for the evolution monitor. Can also be used separately to
+ * provide basic status information without having to use the full evolution monitor.
+ * @author Daniel Dyer
+ */
+public class StatusBar extends Box implements IslandEvolutionObserver<Object>
+{
+ private final JLabel generationsLabel = new JLabel("N/A", JLabel.RIGHT);
+ private final JLabel timeLabel = new JLabel("N/A", JLabel.RIGHT);
+ private final JLabel populationLabel = new JLabel("N/A", JLabel.RIGHT);
+ private final JLabel elitismLabel = new JLabel("N/A", JLabel.RIGHT);
+
+ private final AtomicInteger islandPopulationSize = new AtomicInteger(-1);
+ private long elapsedTime;
+ private long epochTime;
+
+
+ /**
+ * Creates a status bar configured for non-island evolution.
+ */
+ public StatusBar()
+ {
+ this(false);
+ }
+
+
+ /**
+ * @param islands Whether the status bar should be configured for updates from
+ * {@link org.uncommons.watchmaker.framework.islands.IslandEvolution}. Set this
+ * parameter to false when using a standard {@link org.uncommons.watchmaker.framework.EvolutionEngine}
+ */
+ public StatusBar(boolean islands)
+ {
+ super(BoxLayout.X_AXIS);
+ add(new JLabel("Population: "));
+ add(populationLabel);
+ add(createHorizontalStrut(15));
+ add(new JLabel("Elitism: "));
+ add(elitismLabel);
+ add(createHorizontalStrut(15));
+ add(new JLabel(islands ? "Epochs: " : "Generations: "));
+ add(generationsLabel);
+ add(createHorizontalStrut(15));
+ add(new JLabel("Elapsed Time: "));
+ add(timeLabel);
+ setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 5));
+
+ // Set component names for easy look-up from tests.
+ populationLabel.setName("Population");
+ elitismLabel.setName("Elitism");
+ generationsLabel.setName("Generations");
+ timeLabel.setName("Time");
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public void populationUpdate(final PopulationData<?> populationData)
+ {
+ SwingUtilities.invokeLater(new Runnable()
+ {
+ public void run()
+ {
+ if (populationData.getGenerationNumber() == 0)
+ {
+ int islandSize = islandPopulationSize.get();
+ if (islandSize > 0)
+ {
+ int islandCount = populationData.getPopulationSize() / islandSize;
+ populationLabel.setText(islandCount + "x" + islandSize);
+ elitismLabel.setText(islandCount + "x" + populationData.getEliteCount());
+ }
+ else
+ {
+ populationLabel.setText(String.valueOf(populationData.getPopulationSize()));
+ elitismLabel.setText(String.valueOf(populationData.getEliteCount()));
+ }
+ }
+ generationsLabel.setText(String.valueOf(populationData.getGenerationNumber() + 1));
+ elapsedTime = populationData.getElapsedTime();
+ epochTime = 0;
+ timeLabel.setText(formatTime(elapsedTime));
+ }
+ });
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public void islandPopulationUpdate(int islandIndex,
+ final PopulationData<? extends Object> populationData)
+ {
+ islandPopulationSize.compareAndSet(-1, populationData.getPopulationSize());
+ SwingUtilities.invokeLater(new Runnable()
+ {
+ public void run()
+ {
+ // Only update the label if the time has advanced. Sometimes, due to threading
+ // variations, later updates have shorter elapsed times.
+ if (populationData.getElapsedTime() > epochTime)
+ {
+ epochTime = populationData.getElapsedTime();
+ timeLabel.setText(formatTime(elapsedTime + epochTime));
+ }
+ }
+ });
+ }
+
+
+ private String formatTime(long time)
+ {
+ long seconds = time / 1000;
+ long minutes = seconds / 60;
+ seconds %= 60;
+ long hours = minutes / 60;
+ minutes %= 60;
+ StringBuilder buffer = new StringBuilder();
+ if (hours < 10)
+ {
+ buffer.append('0');
+ }
+ buffer.append(hours);
+ buffer.append(':');
+ if (minutes < 10)
+ {
+ buffer.append('0');
+ }
+ buffer.append(minutes);
+ buffer.append(':');
+ if (seconds < 10)
+ {
+ buffer.append('0');
+ }
+ buffer.append(seconds);
+ return buffer.toString();
+ }
+}