summaryrefslogtreecommitdiff
path: root/elki/src/main/java/de/lmu/ifi/dbs/elki/gui
diff options
context:
space:
mode:
Diffstat (limited to 'elki/src/main/java/de/lmu/ifi/dbs/elki/gui')
-rw-r--r--elki/src/main/java/de/lmu/ifi/dbs/elki/gui/GUIUtil.java1
-rw-r--r--elki/src/main/java/de/lmu/ifi/dbs/elki/gui/configurator/AbstractParameterConfigurator.java1
-rw-r--r--elki/src/main/java/de/lmu/ifi/dbs/elki/gui/configurator/AbstractSingleParameterConfigurator.java1
-rw-r--r--elki/src/main/java/de/lmu/ifi/dbs/elki/gui/configurator/ClassListParameterConfigurator.java1
-rw-r--r--elki/src/main/java/de/lmu/ifi/dbs/elki/gui/configurator/ClassParameterConfigurator.java1
-rw-r--r--elki/src/main/java/de/lmu/ifi/dbs/elki/gui/configurator/ConfiguratorPanel.java1
-rw-r--r--elki/src/main/java/de/lmu/ifi/dbs/elki/gui/configurator/EnumParameterConfigurator.java1
-rw-r--r--elki/src/main/java/de/lmu/ifi/dbs/elki/gui/configurator/FileParameterConfigurator.java1
-rw-r--r--elki/src/main/java/de/lmu/ifi/dbs/elki/gui/configurator/FlagParameterConfigurator.java1
-rw-r--r--elki/src/main/java/de/lmu/ifi/dbs/elki/gui/configurator/ParameterConfigurator.java28
-rw-r--r--elki/src/main/java/de/lmu/ifi/dbs/elki/gui/configurator/TextParameterConfigurator.java1
-rw-r--r--elki/src/main/java/de/lmu/ifi/dbs/elki/gui/icons/StockIcon.java1
-rw-r--r--elki/src/main/java/de/lmu/ifi/dbs/elki/gui/minigui/MiniGUI.java519
-rw-r--r--elki/src/main/java/de/lmu/ifi/dbs/elki/gui/multistep/MultiStepGUI.java1
-rw-r--r--elki/src/main/java/de/lmu/ifi/dbs/elki/gui/multistep/panels/AlgorithmTabPanel.java1
-rw-r--r--elki/src/main/java/de/lmu/ifi/dbs/elki/gui/multistep/panels/EvaluationTabPanel.java1
-rw-r--r--elki/src/main/java/de/lmu/ifi/dbs/elki/gui/multistep/panels/InputTabPanel.java1
-rw-r--r--elki/src/main/java/de/lmu/ifi/dbs/elki/gui/multistep/panels/LoggingTabPanel.java6
-rw-r--r--elki/src/main/java/de/lmu/ifi/dbs/elki/gui/multistep/panels/OutputTabPanel.java1
-rw-r--r--elki/src/main/java/de/lmu/ifi/dbs/elki/gui/multistep/panels/ParameterTabPanel.java1
-rw-r--r--elki/src/main/java/de/lmu/ifi/dbs/elki/gui/multistep/panels/SavedSettingsTabPanel.java1
-rw-r--r--elki/src/main/java/de/lmu/ifi/dbs/elki/gui/util/ClassTree.java28
-rw-r--r--elki/src/main/java/de/lmu/ifi/dbs/elki/gui/util/DynamicParameters.java7
-rw-r--r--elki/src/main/java/de/lmu/ifi/dbs/elki/gui/util/LogPane.java1
-rw-r--r--elki/src/main/java/de/lmu/ifi/dbs/elki/gui/util/LogPanel.java1
-rw-r--r--elki/src/main/java/de/lmu/ifi/dbs/elki/gui/util/ParameterTable.java1
-rw-r--r--elki/src/main/java/de/lmu/ifi/dbs/elki/gui/util/ParametersModel.java1
-rw-r--r--elki/src/main/java/de/lmu/ifi/dbs/elki/gui/util/SavedSettingsFile.java1
-rw-r--r--elki/src/main/java/de/lmu/ifi/dbs/elki/gui/util/TreePopup.java1
29 files changed, 449 insertions, 163 deletions
diff --git a/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/GUIUtil.java b/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/GUIUtil.java
index b7d4ee18..210f4e2e 100644
--- a/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/GUIUtil.java
+++ b/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/GUIUtil.java
@@ -35,6 +35,7 @@ import de.lmu.ifi.dbs.elki.logging.Logging;
* GUI utilities.
*
* @author Erich Schubert
+ * @since 0.5.5
*/
public final class GUIUtil {
/**
diff --git a/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/configurator/AbstractParameterConfigurator.java b/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/configurator/AbstractParameterConfigurator.java
index d1d89d69..9905ad59 100644
--- a/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/configurator/AbstractParameterConfigurator.java
+++ b/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/configurator/AbstractParameterConfigurator.java
@@ -43,6 +43,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.Parameter;
* Abstract class to produce a configurator for a particular parameter.
*
* @author Erich Schubert
+ * @since 0.4.0
*
* @apiviz.has StockIcon
*
diff --git a/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/configurator/AbstractSingleParameterConfigurator.java b/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/configurator/AbstractSingleParameterConfigurator.java
index de040cc7..bb298994 100644
--- a/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/configurator/AbstractSingleParameterConfigurator.java
+++ b/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/configurator/AbstractSingleParameterConfigurator.java
@@ -34,6 +34,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.Parameter;
* Base class for MiniGUI input helpers
*
* @author Erich Schubert
+ * @since 0.4.0
*
* @param <T> Parameter type
*/
diff --git a/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/configurator/ClassListParameterConfigurator.java b/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/configurator/ClassListParameterConfigurator.java
index ddc25f2e..0d76aa95 100644
--- a/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/configurator/ClassListParameterConfigurator.java
+++ b/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/configurator/ClassListParameterConfigurator.java
@@ -56,6 +56,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.Parameter;
* Additionally, the classes can in turn have additional parameters.
*
* @author Erich Schubert
+ * @since 0.4.0
*
* @apiviz.uses ClassListParameter
* @apiviz.uses ClassTree
diff --git a/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/configurator/ClassParameterConfigurator.java b/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/configurator/ClassParameterConfigurator.java
index 7bc81fed..07f1e14f 100644
--- a/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/configurator/ClassParameterConfigurator.java
+++ b/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/configurator/ClassParameterConfigurator.java
@@ -59,6 +59,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.Parameter;
* Additionally, the classes can in turn have additional parameters.
*
* @author Erich Schubert
+ * @since 0.4.0
*
* @apiviz.uses ClassParameter
*/
diff --git a/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/configurator/ConfiguratorPanel.java b/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/configurator/ConfiguratorPanel.java
index 873417a0..b07aed06 100644
--- a/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/configurator/ConfiguratorPanel.java
+++ b/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/configurator/ConfiguratorPanel.java
@@ -48,6 +48,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.Parameter;
* A panel that contains configurators for parameters.
*
* @author Erich Schubert
+ * @since 0.4.0
*
* @apiviz.landmark
* @apiviz.has de.lmu.ifi.dbs.elki.gui.configurator.ParameterConfigurator
diff --git a/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/configurator/EnumParameterConfigurator.java b/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/configurator/EnumParameterConfigurator.java
index 416b47bb..95ae3a04 100644
--- a/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/configurator/EnumParameterConfigurator.java
+++ b/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/configurator/EnumParameterConfigurator.java
@@ -40,6 +40,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.EnumParameter;
* TODO: offer radio buttons when just a few choices are available?
*
* @author Erich Schubert
+ * @since 0.4.0
*
* @apiviz.uses EnumParameter
*/
diff --git a/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/configurator/FileParameterConfigurator.java b/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/configurator/FileParameterConfigurator.java
index f7218f35..9d3d53e5 100644
--- a/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/configurator/FileParameterConfigurator.java
+++ b/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/configurator/FileParameterConfigurator.java
@@ -43,6 +43,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.FileParameter;
* Provide a configuration panel to choose a file with a file selector button.
*
* @author Erich Schubert
+ * @since 0.4.0
*
* @apiviz.uses FileParameter
*/
diff --git a/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/configurator/FlagParameterConfigurator.java b/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/configurator/FlagParameterConfigurator.java
index 052c6ac6..5b3d42c7 100644
--- a/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/configurator/FlagParameterConfigurator.java
+++ b/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/configurator/FlagParameterConfigurator.java
@@ -37,6 +37,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.Flag;
* Provide a configuration panel to modify a boolean via a checkbox.
*
* @author Erich Schubert
+ * @since 0.4.0
*
* @apiviz.uses Flag
*/
diff --git a/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/configurator/ParameterConfigurator.java b/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/configurator/ParameterConfigurator.java
index 217f3632..88b93d25 100644
--- a/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/configurator/ParameterConfigurator.java
+++ b/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/configurator/ParameterConfigurator.java
@@ -29,12 +29,40 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.ListParamet
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.TrackParameters;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.Parameter;
+/**
+ * Interface for different configuration assistants for the multistep GUI.
+ *
+ * @author Erich Schubert
+ * @since 0.4.0
+ */
public interface ParameterConfigurator {
+ /**
+ * Add a parameter to the panel.
+ *
+ * @param owner Owning ("parent") object
+ * @param param Parameter
+ * @param track Parameter tracker
+ */
public void addParameter(Object owner, Parameter<?> param, TrackParameters track);
+ /**
+ * Add a change listener
+ *
+ * @param listener Change listener
+ */
public void addChangeListener(ChangeListener listener);
+ /**
+ * Remove a change listener
+ *
+ * @param listener Change listener
+ */
public void removeChangeListener(ChangeListener listener);
+ /**
+ * Append the parameters to a list.
+ *
+ * @param params Parameter list (output)
+ */
public void appendParameters(ListParameterization params);
} \ No newline at end of file
diff --git a/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/configurator/TextParameterConfigurator.java b/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/configurator/TextParameterConfigurator.java
index 27c9d531..6c86f18a 100644
--- a/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/configurator/TextParameterConfigurator.java
+++ b/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/configurator/TextParameterConfigurator.java
@@ -38,6 +38,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.Parameter;
* Provide a configuration panel to input an arbitrary text parameter.
*
* @author Erich Schubert
+ * @since 0.4.0
*
* @apiviz.uses Parameter
*/
diff --git a/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/icons/StockIcon.java b/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/icons/StockIcon.java
index c0c7b91c..de450f4a 100644
--- a/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/icons/StockIcon.java
+++ b/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/icons/StockIcon.java
@@ -36,6 +36,7 @@ import de.lmu.ifi.dbs.elki.logging.LoggingUtil;
* Stock icon library for use in the GUI.
*
* @author Erich Schubert
+ * @since 0.4.0
*
* @apiviz.landmark
*/
diff --git a/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/minigui/MiniGUI.java b/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/minigui/MiniGUI.java
index 6edaa95d..7cba1e97 100644
--- a/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/minigui/MiniGUI.java
+++ b/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/minigui/MiniGUI.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.gui.minigui;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2015
+ Copyright (C) 2016
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -36,7 +36,6 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
-import java.util.logging.Level;
import javax.swing.AbstractAction;
import javax.swing.AbstractListModel;
@@ -46,8 +45,10 @@ import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
+import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
+import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.SwingWorker;
import javax.swing.event.TableModelEvent;
@@ -81,6 +82,7 @@ import de.lmu.ifi.dbs.elki.workflow.OutputStep;
* Minimal GUI built around a table-based parameter editor.
*
* @author Erich Schubert
+ * @since 0.3
*
* @apiviz.composedOf SettingsComboboxModel
* @apiviz.composedOf LoggingStep
@@ -140,6 +142,11 @@ public class MiniGUI extends AbstractApplication {
protected SavedSettingsFile store = new SavedSettingsFile(SAVED_SETTINGS_FILENAME);
/**
+ * Combo box for choosing the application to run.
+ */
+ protected JComboBox<String> appCombo;
+
+ /**
* Combo box for saved settings.
*/
protected JComboBox<String> savedCombo;
@@ -160,12 +167,22 @@ public class MiniGUI extends AbstractApplication {
private Class<? extends AbstractApplication> maincls = KDDCLIApplication.class;
/**
+ * Command line output field.
+ */
+ private JTextField commandLine;
+
+ /**
+ * Prefix for application package.
+ */
+ private String APP_PREFIX = AbstractApplication.class.getPackage().getName() + ".";
+
+ /**
* Constructor.
*/
public MiniGUI() {
super();
// Create and set up the window.
- frame = new JFrame("ELKI MiniGUI");
+ frame = new JFrame("ELKI MiniGUI Command Line Builder");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
try {
frame.setIconImage(new ImageIcon(KDDTask.class.getResource("elki-icon.png")).getImage());
@@ -178,138 +195,11 @@ public class MiniGUI extends AbstractApplication {
panel.setOpaque(true); // content panes must be opaque
panel.setLayout(new GridBagLayout());
- {
- // Button panel
- JPanel buttonPanel = new JPanel();
- buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.X_AXIS));
-
- // Combo box for saved settings
- savedSettingsModel = new SettingsComboboxModel(store);
- savedCombo = new JComboBox<>(savedSettingsModel);
- savedCombo.setEditable(true);
- savedCombo.setSelectedItem("[Saved Settings]");
- buttonPanel.add(savedCombo);
-
- // button to load settings
- JButton loadButton = new JButton("Load");
- loadButton.setMnemonic(KeyEvent.VK_L);
- loadButton.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- String key = savedSettingsModel.getSelectedItem();
- ArrayList<String> settings = store.get(key);
- if(settings != null) {
- outputArea.clear();
- outputArea.publish("Parameters: " + FormatUtil.format(settings, " ") + NEWLINE, Level.INFO);
- doSetParameters(settings);
- }
- }
- });
- buttonPanel.add(loadButton);
- // button to save settings
- JButton saveButton = new JButton("Save");
- saveButton.setMnemonic(KeyEvent.VK_S);
- saveButton.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- String key = savedSettingsModel.getSelectedItem();
- // Stop editing the table.
- parameterTable.editCellAt(-1, -1);
- store.put(key, parameters.serializeParameters());
- try {
- store.save();
- }
- catch(IOException e1) {
- LOG.exception(e1);
- }
- savedSettingsModel.update();
- }
- });
- buttonPanel.add(saveButton);
- // button to remove saved settings
- JButton removeButton = new JButton("Remove");
- removeButton.setMnemonic(KeyEvent.VK_E);
- removeButton.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- String key = savedSettingsModel.getSelectedItem();
- store.remove(key);
- try {
- store.save();
- }
- catch(IOException e1) {
- LOG.exception(e1);
- }
- savedCombo.setSelectedItem("[Saved Settings]");
- savedSettingsModel.update();
- }
- });
- buttonPanel.add(removeButton);
-
- // button to launch the task
- runButton = new JButton("Run Task");
- runButton.setMnemonic(KeyEvent.VK_R);
- runButton.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- startTask();
- }
- });
- buttonPanel.add(runButton);
-
- GridBagConstraints constraints = new GridBagConstraints();
- constraints.fill = GridBagConstraints.HORIZONTAL;
- constraints.gridx = 0;
- constraints.gridy = 1;
- constraints.weightx = 1.0;
- constraints.weighty = 0.01;
- panel.add(buttonPanel, constraints);
- }
-
- {
- // Setup parameter storage and table model
- this.parameters = new DynamicParameters();
- ParametersModel parameterModel = new ParametersModel(parameters);
- parameterModel.addTableModelListener(new TableModelListener() {
- @Override
- public void tableChanged(TableModelEvent e) {
- // logger.debug("Change event.");
- updateParameterTable();
- }
- });
-
- // Create parameter table
- parameterTable = new ParameterTable(frame, parameterModel, parameters);
- // Create the scroll pane and add the table to it.
- JScrollPane scrollPane = new JScrollPane(parameterTable);
-
- // Add the scroll pane to this panel.
- GridBagConstraints constraints = new GridBagConstraints();
- constraints.fill = GridBagConstraints.BOTH;
- constraints.gridx = 0;
- constraints.gridy = 0;
- constraints.weightx = 1;
- constraints.weighty = 1;
- panel.add(scrollPane, constraints);
- }
-
- {
- // setup text output area
- outputArea = new LogPanel();
-
- // Create the scroll pane and add the table to it.
- JScrollPane outputPane = new JScrollPane(outputArea);
- outputPane.setPreferredSize(new Dimension(800, 400));
-
- // Add the output pane to the bottom
- GridBagConstraints constraints = new GridBagConstraints();
- constraints.fill = GridBagConstraints.BOTH;
- constraints.gridx = 0;
- constraints.gridy = 2;
- constraints.weightx = 1;
- constraints.weighty = 1;
- panel.add(outputPane, constraints);
- }
+ setupAppChooser();
+ setupParameterTable();
+ setupLoadSaveButtons();
+ setupCommandLine();
+ setupLoggingArea();
// load saved settings (we wanted to have the logger first!)
try {
@@ -349,14 +239,222 @@ public class MiniGUI extends AbstractApplication {
}
/**
+ * Setup the application chooser.
+ */
+ private void setupAppChooser() {
+ // Configurator to choose the main application
+ appCombo = new JComboBox<>();
+ for(Class<?> clz : ELKIServiceRegistry.findAllImplementations(AbstractApplication.class)) {
+ String nam = clz.getCanonicalName();
+ if(nam == null || clz.getCanonicalName().contains("GUI")) {
+ continue;
+ }
+ if(nam.startsWith(APP_PREFIX)) {
+ nam = nam.substring(APP_PREFIX.length());
+ }
+ appCombo.addItem(nam);
+ }
+ appCombo.setEditable(true);
+ String sel = maincls.getCanonicalName();
+ if(sel.startsWith(APP_PREFIX)) {
+ sel = sel.substring(APP_PREFIX.length());
+ }
+ appCombo.setSelectedItem(sel);
+ appCombo.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ if("comboBoxChanged".equals(e.getActionCommand())) {
+ Class<? extends AbstractApplication> clz = ELKIServiceRegistry.findImplementation(AbstractApplication.class, (String) appCombo.getSelectedItem());
+ if(clz != null) {
+ maincls = clz;
+ updateParameterTable();
+ }
+ else {
+ LOG.warning("Main class name not found.");
+ }
+ }
+ }
+ });
+
+ GridBagConstraints constraints = new GridBagConstraints();
+ constraints.fill = GridBagConstraints.BOTH;
+ constraints.gridx = 0;
+ constraints.gridy = 0;
+ constraints.weightx = 1;
+ constraints.weighty = .01;
+ panel.add(appCombo, constraints);
+ }
+
+ /**
+ * Setup the parameter table
+ */
+ private void setupParameterTable() {
+ // Setup parameter storage and table model
+ this.parameters = new DynamicParameters();
+ ParametersModel parameterModel = new ParametersModel(parameters);
+ parameterModel.addTableModelListener(new TableModelListener() {
+ @Override
+ public void tableChanged(TableModelEvent e) {
+ // logger.debug("Change event.");
+ updateParameterTable();
+ }
+ });
+
+ // Create parameter table
+ parameterTable = new ParameterTable(frame, parameterModel, parameters);
+ // Create the scroll pane and add the table to it.
+ JScrollPane scrollPane = new JScrollPane(parameterTable);
+
+ // Add the scroll pane to this panel.
+ GridBagConstraints constraints = new GridBagConstraints();
+ constraints.fill = GridBagConstraints.BOTH;
+ constraints.gridx = 0;
+ constraints.gridy = 1;
+ constraints.weightx = 1;
+ constraints.weighty = 1;
+ panel.add(scrollPane, constraints);
+ }
+
+ /**
+ * Create the load and save buttons.
+ */
+ private void setupLoadSaveButtons() {
+ // Button panel
+ JPanel buttonPanel = new JPanel();
+ buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.X_AXIS));
+
+ // Combo box for saved settings
+ savedSettingsModel = new SettingsComboboxModel(store);
+ savedCombo = new JComboBox<>(savedSettingsModel);
+ savedCombo.setEditable(true);
+ savedCombo.setSelectedItem("[Saved Settings]");
+ buttonPanel.add(savedCombo);
+
+ // button to load settings
+ JButton loadButton = new JButton("Load");
+ loadButton.setMnemonic(KeyEvent.VK_L);
+ loadButton.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ String key = savedSettingsModel.getSelectedItem();
+ ArrayList<String> settings = store.get(key);
+ if(settings != null) {
+ doSetParameters(settings);
+ }
+ }
+ });
+ buttonPanel.add(loadButton);
+ // button to save settings
+ JButton saveButton = new JButton("Save");
+ saveButton.setMnemonic(KeyEvent.VK_S);
+ saveButton.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ String key = savedSettingsModel.getSelectedItem();
+ // Stop editing the table.
+ parameterTable.editCellAt(-1, -1);
+ ArrayList<String> list = new ArrayList<>(parameters.size() * 2 + 1);
+ list.add(maincls.getCanonicalName());
+ parameters.serializeParameters(list);
+ store.put(key, list);
+ try {
+ store.save();
+ }
+ catch(IOException e1) {
+ LOG.exception(e1);
+ }
+ savedSettingsModel.update();
+ }
+ });
+ buttonPanel.add(saveButton);
+ // button to remove saved settings
+ JButton removeButton = new JButton("Remove");
+ removeButton.setMnemonic(KeyEvent.VK_E);
+ removeButton.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ String key = savedSettingsModel.getSelectedItem();
+ store.remove(key);
+ try {
+ store.save();
+ }
+ catch(IOException e1) {
+ LOG.exception(e1);
+ }
+ savedCombo.setSelectedItem("[Saved Settings]");
+ savedSettingsModel.update();
+ }
+ });
+ buttonPanel.add(removeButton);
+
+ // button to launch the task
+ runButton = new JButton("Run Task");
+ runButton.setMnemonic(KeyEvent.VK_R);
+ runButton.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ startTask();
+ }
+ });
+ buttonPanel.add(runButton);
+
+ GridBagConstraints constraints = new GridBagConstraints();
+ constraints.fill = GridBagConstraints.HORIZONTAL;
+ constraints.gridx = 0;
+ constraints.gridy = 2;
+ constraints.weightx = 1.0;
+ constraints.weighty = 0.01;
+ panel.add(buttonPanel, constraints);
+ }
+
+ /**
+ * Setup command line field
+ */
+ private void setupCommandLine() {
+ // setup text output area
+ commandLine = new JTextField();
+ commandLine.setEditable(false); // FIXME: Make editable!
+
+ // Add the output pane to the bottom
+ GridBagConstraints constraints = new GridBagConstraints();
+ constraints.fill = GridBagConstraints.BOTH;
+ constraints.gridx = 0;
+ constraints.gridy = 3;
+ constraints.weightx = 1;
+ constraints.weighty = .01;
+ panel.add(commandLine, constraints);
+ }
+
+ /**
+ * Setup logging area
+ */
+ private void setupLoggingArea() {
+ // setup text output area
+ outputArea = new LogPanel();
+
+ // Create the scroll pane and add the table to it.
+ JScrollPane outputPane = new JScrollPane(outputArea);
+ outputPane.setPreferredSize(new Dimension(800, 400));
+
+ // Add the output pane to the bottom
+ GridBagConstraints constraints = new GridBagConstraints();
+ constraints.fill = GridBagConstraints.BOTH;
+ constraints.gridx = 0;
+ constraints.gridy = 4;
+ constraints.weightx = 1;
+ constraints.weighty = 1;
+ panel.add(outputPane, constraints);
+ }
+
+ /**
* Serialize the parameter table and run setParameters().
*/
protected void updateParameterTable() {
parameterTable.setEnabled(false);
- ArrayList<String> params = parameters.serializeParameters();
- outputArea.clear();
- outputArea.publish("Parameters: " + FormatUtil.format(params, " ") + NEWLINE, Level.INFO);
- doSetParameters(params);
+ ArrayList<String> list = new ArrayList<String>(parameters.size() * 2 + 1);
+ list.add(maincls.getCanonicalName());
+ parameters.serializeParameters(list);
+ doSetParameters(list);
parameterTable.setEnabled(true);
}
@@ -366,6 +464,16 @@ public class MiniGUI extends AbstractApplication {
* @param params Parameters
*/
protected void doSetParameters(List<String> params) {
+ if(params.size() > 0) {
+ String first = params.get(0);
+ if(!first.startsWith("-")) {
+ Class<? extends AbstractApplication> c = ELKIServiceRegistry.findImplementation(AbstractApplication.class, first);
+ if(c != null) {
+ maincls = c;
+ params.remove(0);
+ }
+ }
+ }
SerializedParameterization config = new SerializedParameterization(params);
TrackParameters track = new TrackParameters(config);
track.tryInstantiate(LoggingStep.class);
@@ -380,6 +488,13 @@ public class MiniGUI extends AbstractApplication {
List<String> remainingParameters = config.getRemainingParameters();
+ outputArea.clear();
+ String mainnam = maincls.getCanonicalName();
+ if(mainnam.startsWith(APP_PREFIX)) {
+ mainnam = mainnam.substring(APP_PREFIX.length());
+ }
+ commandLine.setText(format(mainnam, params));
+
// update table:
parameterTable.removeEditor();
parameterTable.setEnabled(false);
@@ -403,6 +518,97 @@ public class MiniGUI extends AbstractApplication {
}
/**
+ * Format objects to a command line.
+ *
+ * @param params Parameters to format (Strings, or list of strings)
+ * @return Formatted string
+ */
+ private String format(Object... params) {
+ StringBuilder buf = new StringBuilder();
+ for(Object p : params) {
+ if(p instanceof String) {
+ formatTo(buf, (String) p);
+ }
+ else if(p instanceof List) {
+ formatTo(buf, (List<?>) p);
+ }
+ else {
+ LOG.warning("Incorrect object type: " + p.getClass());
+ }
+ }
+ return buf.toString();
+ }
+
+ /**
+ * Format a list of strings to a buffer.
+ *
+ * @param buf Output buffer
+ * @param params List of strings
+ */
+ private void formatTo(StringBuilder buf, List<?> params) {
+ for(Object p : params) {
+ if(p instanceof String) {
+ formatTo(buf, (String) p);
+ }
+ else {
+ LOG.warning("Incorrect object type: " + p.getClass());
+ }
+ }
+ }
+
+ /**
+ * Format a single string for the command line.
+ *
+ * @param buf Output buffer
+ * @param s String
+ */
+ private void formatTo(StringBuilder buf, String s) {
+ if(s == null || s.length() == 0) {
+ return;
+ }
+ if(buf.length() > 0) {
+ buf.append(' ');
+ }
+ // Test for escaping necessary
+ int escape = 0;
+ for(int i = 0, l = s.length(); i < l; i++) {
+ char c = s.charAt(i);
+ if(c == '\\') {
+ escape |= 8;
+ }
+ else if(c <= ' ' || c >= 128 || c == '<' || c == '>' || c == '|' || c == '$') {
+ escape |= 1;
+ }
+ else if(c == '"') {
+ escape |= 2;
+ }
+ else if(c == '\'') {
+ escape |= 4;
+ }
+ }
+ if(escape == 0) {
+ buf.append(s); // No escaping.
+ }
+ else if((escape & 10) == 0) {
+ buf.append('"').append(s).append('"');
+ }
+ else if((escape & 12) == 0) {
+ buf.append('\'').append(s).append('\'');
+ }
+ else { // Full escaping.
+ buf.append('"');
+ for(int i = 0, l = s.length(); i < l; i++) {
+ char c = s.charAt(i);
+ if(c == '"' || c == '\\' || c == '$') {
+ buf.append('\\');
+ }
+ buf.append(c);
+ }
+ buf.append('"');
+ }
+ }
+
+ /**
* Auto-load the last task from the history file.
*/
protected void loadLatest() {
@@ -420,14 +626,13 @@ public class MiniGUI extends AbstractApplication {
protected void startTask() {
parameterTable.editCellAt(-1, -1);
parameterTable.setEnabled(false);
- final ArrayList<String> params = parameters.serializeParameters();
+ final ArrayList<String> params = new ArrayList<>(parameters.size() * 2);
+ parameters.serializeParameters(params);
parameterTable.setEnabled(true);
runButton.setEnabled(false);
outputArea.clear();
- outputArea.publish("Running: " + FormatUtil.format(params, " ") + NEWLINE, Level.INFO);
-
SwingWorker<Void, Void> r = new SwingWorker<Void, Void>() {
@Override
public Void doInBackground() {
@@ -493,6 +698,34 @@ public class MiniGUI extends AbstractApplication {
* @param args command line parameters
*/
public static void main(final String[] args) {
+ // Detect the common problem of an incomplete class path:
+ try {
+ Class<?> clz = ClassLoader.getSystemClassLoader().loadClass("de.lmu.ifi.dbs.elki.database.ids.DBIDUtil");
+ clz.getMethod("newHashSet").invoke(null);
+ }
+ catch(ReflectiveOperationException e) {
+ StringBuilder msg = new StringBuilder();
+ msg.append("Your Java class path is incomplete.\n");
+ if(e.getCause() != null) {
+ msg.append(e.getCause().toString()).append("\n");
+ }
+ else {
+ msg.append(e.toString()).append("\n");
+ }
+ msg.append("Make sure you have all the required jars on the classpath.\n");
+ msg.append("On the home page, you can find a 'elki-bundle' which should include everything.");
+ JOptionPane.showMessageDialog(null, msg, "ClassPath incomplete", JOptionPane.ERROR_MESSAGE);
+ return;
+ }
+ // Detect the broken Ubuntu jAyatana hack;
+ String toolopt = System.getenv("JAVA_TOOL_OPTION");
+ if(toolopt != null && toolopt.indexOf("jayatana") >= 0) {
+ StringBuilder msg = new StringBuilder();
+ msg.append("The Ubuntu JAyatana 'global menu support' hack is known to cause problems with many Java applications.\n");
+ msg.append("Please unset JAVA_TOOL_OPTION.");
+ JOptionPane.showMessageDialog(null, msg, "Incompatible with JAyatana", JOptionPane.ERROR_MESSAGE);
+ return;
+ }
GUIUtil.logUncaughtExceptions(LOG);
GUIUtil.setLookAndFeel();
OutputStep.setDefaultHandlerVisualizer();
@@ -549,7 +782,7 @@ public class MiniGUI extends AbstractApplication {
*
* @apiviz.composedOf de.lmu.ifi.dbs.elki.gui.util.SavedSettingsFile
*/
- class SettingsComboboxModel extends AbstractListModel<String>implements ComboBoxModel<String> {
+ class SettingsComboboxModel extends AbstractListModel<String> implements ComboBoxModel<String> {
/**
* Serial version.
*/
diff --git a/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/multistep/MultiStepGUI.java b/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/multistep/MultiStepGUI.java
index dacbe361..36aa79fe 100644
--- a/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/multistep/MultiStepGUI.java
+++ b/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/multistep/MultiStepGUI.java
@@ -61,6 +61,7 @@ import de.lmu.ifi.dbs.elki.workflow.OutputStep;
* Experimenter-style multi step GUI.
*
* @author Erich Schubert
+ * @since 0.4.0
*
* @apiviz.landmark
* @apiviz.composedOf AlgorithmTabPanel
diff --git a/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/multistep/panels/AlgorithmTabPanel.java b/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/multistep/panels/AlgorithmTabPanel.java
index c0dda863..fb9bd116 100644
--- a/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/multistep/panels/AlgorithmTabPanel.java
+++ b/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/multistep/panels/AlgorithmTabPanel.java
@@ -34,6 +34,7 @@ import de.lmu.ifi.dbs.elki.workflow.AlgorithmStep;
* Panel to handle data processing
*
* @author Erich Schubert
+ * @since 0.4.0
*/
public class AlgorithmTabPanel extends ParameterTabPanel {
/**
diff --git a/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/multistep/panels/EvaluationTabPanel.java b/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/multistep/panels/EvaluationTabPanel.java
index 65d53d20..8a8d10b5 100644
--- a/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/multistep/panels/EvaluationTabPanel.java
+++ b/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/multistep/panels/EvaluationTabPanel.java
@@ -35,6 +35,7 @@ import de.lmu.ifi.dbs.elki.workflow.EvaluationStep;
* Panel to handle result evaluation
*
* @author Erich Schubert
+ * @since 0.4.0
*/
public class EvaluationTabPanel extends ParameterTabPanel {
/**
diff --git a/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/multistep/panels/InputTabPanel.java b/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/multistep/panels/InputTabPanel.java
index 7a3ea1f5..cd83a860 100644
--- a/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/multistep/panels/InputTabPanel.java
+++ b/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/multistep/panels/InputTabPanel.java
@@ -31,6 +31,7 @@ import de.lmu.ifi.dbs.elki.workflow.InputStep;
* Panel to handle data input.
*
* @author Erich Schubert
+ * @since 0.4.0
*/
public class InputTabPanel extends ParameterTabPanel {
/**
diff --git a/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/multistep/panels/LoggingTabPanel.java b/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/multistep/panels/LoggingTabPanel.java
index 2dcc38d4..902995ce 100644
--- a/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/multistep/panels/LoggingTabPanel.java
+++ b/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/multistep/panels/LoggingTabPanel.java
@@ -24,9 +24,8 @@ package de.lmu.ifi.dbs.elki.gui.multistep.panels;
*/
import de.lmu.ifi.dbs.elki.application.AbstractApplication;
-import de.lmu.ifi.dbs.elki.logging.LoggingConfiguration;
-import de.lmu.ifi.dbs.elki.logging.LoggingUtil;
import de.lmu.ifi.dbs.elki.logging.Logging.Level;
+import de.lmu.ifi.dbs.elki.logging.LoggingConfiguration;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.WrongParameterValueException;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.Flag;
@@ -36,6 +35,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.StringParameter;
* Panel to handle logging
*
* @author Erich Schubert
+ * @since 0.4.0
*/
public class LoggingTabPanel extends ParameterTabPanel {
/**
@@ -62,7 +62,7 @@ public class LoggingTabPanel extends ParameterTabPanel {
// FIXME: add second level of verbosity!
if (config.grab(debugParam)) {
try {
- LoggingUtil.parseDebugParameter(debugParam);
+ AbstractApplication.Parameterizer.parseDebugParameter(debugParam);
} catch (WrongParameterValueException e) {
de.lmu.ifi.dbs.elki.logging.LoggingUtil.exception(e);
}
diff --git a/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/multistep/panels/OutputTabPanel.java b/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/multistep/panels/OutputTabPanel.java
index cedc5765..29fdf7ff 100644
--- a/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/multistep/panels/OutputTabPanel.java
+++ b/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/multistep/panels/OutputTabPanel.java
@@ -35,6 +35,7 @@ import de.lmu.ifi.dbs.elki.workflow.OutputStep;
* Panel to handle result output / visualization
*
* @author Erich Schubert
+ * @since 0.4.0
*/
public class OutputTabPanel extends ParameterTabPanel {
/**
diff --git a/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/multistep/panels/ParameterTabPanel.java b/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/multistep/panels/ParameterTabPanel.java
index caf9c066..f6985f4f 100644
--- a/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/multistep/panels/ParameterTabPanel.java
+++ b/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/multistep/panels/ParameterTabPanel.java
@@ -51,6 +51,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.TrackParame
* Abstract panel, showing particular options.
*
* @author Erich Schubert
+ * @since 0.4.0
*/
public abstract class ParameterTabPanel extends JPanel implements ChangeListener {
/**
diff --git a/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/multistep/panels/SavedSettingsTabPanel.java b/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/multistep/panels/SavedSettingsTabPanel.java
index 0ea2a34f..ec7b66e6 100644
--- a/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/multistep/panels/SavedSettingsTabPanel.java
+++ b/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/multistep/panels/SavedSettingsTabPanel.java
@@ -47,6 +47,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.SerializedP
* Tab panel to manage saved settings.
*
* @author Erich Schubert
+ * @since 0.4.0
*
* @apiviz.composedOf SavedSettingsTabPanel.SettingsComboboxModel
*/
diff --git a/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/util/ClassTree.java b/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/util/ClassTree.java
index 8c524cdd..3c2a6373 100644
--- a/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/util/ClassTree.java
+++ b/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/util/ClassTree.java
@@ -31,15 +31,16 @@ import javax.swing.tree.TreeNode;
/**
* Build a tree of available classes for use in Swing UIs.
- *
+ *
* @author Erich Schubert
- *
+ * @since 0.7.0
+ *
* @apiviz.has TreeNode
*/
public class ClassTree {
/**
* Build the class tree for a given set of choices.
- *
+ *
* @param choices Class choices
* @param rootpkg Root package name (to strip / hide)
* @return Root node.
@@ -59,7 +60,8 @@ public class ClassTree {
for(Class<?> impl : choices) {
String name = impl.getName();
name = (prefix != null && name.startsWith(prefix)) ? name.substring(prefix.length()) : name;
- MutableTreeNode c = new ClassNode(impl.getName().substring(impl.getPackage().getName().length() + 1), name);
+ int plen = (impl.getPackage() != null) ? impl.getPackage().getName().length() + 1 : 0;
+ MutableTreeNode c = new ClassNode(impl.getName().substring(plen), name);
MutableTreeNode p = null;
int l = name.lastIndexOf('.');
@@ -96,7 +98,7 @@ public class ClassTree {
/**
* Simplify the tree.
- *
+ *
* @param cur Current node
* @param prefix Prefix to add
* @return Replacement node
@@ -133,9 +135,9 @@ public class ClassTree {
/**
* Tree node representing a single class.
- *
+ *
* @author Erich Schubert
- *
+ *
* @apiviz.exclude
*/
public static class PackageNode extends DefaultMutableTreeNode {
@@ -151,7 +153,7 @@ public class ClassTree {
/**
* Current class name.
- *
+ *
* @param display Displayed name
* @param pkgname Actual class name
*/
@@ -162,7 +164,7 @@ public class ClassTree {
/**
* Return the package name.
- *
+ *
* @return Package name
*/
public String getPackageName() {
@@ -172,9 +174,9 @@ public class ClassTree {
/**
* Tree node representing a single class.
- *
+ *
* @author Erich Schubert
- *
+ *
* @apiviz.exclude
*/
public static class ClassNode extends DefaultMutableTreeNode {
@@ -190,7 +192,7 @@ public class ClassTree {
/**
* Current class name.
- *
+ *
* @param display Displayed name
* @param clsname Actual class name
*/
@@ -201,7 +203,7 @@ public class ClassTree {
/**
* Return the class name.
- *
+ *
* @return Class name
*/
public String getClassName() {
diff --git a/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/util/DynamicParameters.java b/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/util/DynamicParameters.java
index 2aae45d4..10cc79a3 100644
--- a/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/util/DynamicParameters.java
+++ b/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/util/DynamicParameters.java
@@ -39,6 +39,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.StringParameter;
* correct.
*
* @author Erich Schubert
+ * @since 0.3
*
* @apiviz.owns de.lmu.ifi.dbs.elki.gui.util.DynamicParameters.RemainingOptions
*/
@@ -206,10 +207,9 @@ public class DynamicParameters {
/**
* Serialize parameters into an array list to pass to setParameters()
*
- * @return Array list of String parameters.
+ * @param p Output list (will not be emptied)
*/
- public synchronized ArrayList<String> serializeParameters() {
- ArrayList<String> p = new ArrayList<>(2 * parameters.size());
+ public synchronized void serializeParameters(ArrayList<String> p) {
for(Node t : parameters) {
if(t.param != null) {
if(t.param instanceof RemainingOptions) {
@@ -232,7 +232,6 @@ public class DynamicParameters {
}
}
}
- return p;
}
/**
diff --git a/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/util/LogPane.java b/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/util/LogPane.java
index 17c52cea..c42a2ed7 100644
--- a/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/util/LogPane.java
+++ b/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/util/LogPane.java
@@ -46,6 +46,7 @@ import de.lmu.ifi.dbs.elki.logging.progress.ProgressLogRecord;
* {@link #becomeDefaultLogger()} to register as default logger in ELKI.
*
* @author Erich Schubert
+ * @since 0.3
*
* @apiviz.uses LoggingConfiguration
* @apiviz.uses de.lmu.ifi.dbs.elki.logging.ELKILogRecord
diff --git a/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/util/LogPanel.java b/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/util/LogPanel.java
index dbe87b58..9507c8eb 100644
--- a/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/util/LogPanel.java
+++ b/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/util/LogPanel.java
@@ -48,6 +48,7 @@ import de.lmu.ifi.dbs.elki.logging.progress.StepProgress;
* Panel that contains a text logging pane ({@link LogPane}) and progress bars.
*
* @author Erich Schubert
+ * @since 0.3
*
* @apiviz.owns LogPane
* @apiviz.uses LoggingConfiguration
diff --git a/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/util/ParameterTable.java b/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/util/ParameterTable.java
index a08341db..a5782ca9 100644
--- a/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/util/ParameterTable.java
+++ b/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/util/ParameterTable.java
@@ -73,6 +73,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.Parameter;
* Class showing a table of ELKI parameters.
*
* @author Erich Schubert
+ * @since 0.3
*
* @apiviz.composedOf ParametersModel
* @apiviz.owns de.lmu.ifi.dbs.elki.gui.util.ParameterTable.ColorfulRenderer
diff --git a/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/util/ParametersModel.java b/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/util/ParametersModel.java
index d864cc9b..66593c20 100644
--- a/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/util/ParametersModel.java
+++ b/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/util/ParametersModel.java
@@ -32,6 +32,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.Parameter;
* A Swing TableModel that uses a {@link DynamicParameters} object as storage.
*
* @author Erich Schubert
+ * @since 0.3
*/
public class ParametersModel extends AbstractTableModel {
/**
diff --git a/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/util/SavedSettingsFile.java b/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/util/SavedSettingsFile.java
index f8f4c990..6f31a2c6 100644
--- a/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/util/SavedSettingsFile.java
+++ b/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/util/SavedSettingsFile.java
@@ -39,6 +39,7 @@ import de.lmu.ifi.dbs.elki.utilities.pairs.Pair;
* Class to manage saved settings in a text file.
*
* @author Erich Schubert
+ * @since 0.3
*/
public class SavedSettingsFile implements Iterable<Pair<String, ArrayList<String>>> {
/**
diff --git a/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/util/TreePopup.java b/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/util/TreePopup.java
index 19413c53..6bfb6a2a 100644
--- a/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/util/TreePopup.java
+++ b/elki/src/main/java/de/lmu/ifi/dbs/elki/gui/util/TreePopup.java
@@ -62,6 +62,7 @@ import javax.swing.tree.TreeModel;
* Popup menu that contains a JTree.
*
* @author Erich Schubert
+ * @since 0.7.0
*/
public class TreePopup extends JPopupMenu {
/**