diff options
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.java | 165 |
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(); + } +} |