X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;f=src%2Fmain%2Fjava%2Fnet%2Fpterodactylus%2Fsonitus%2Fgui%2FPipelinePanel.java;h=133ec7044696fdbb8f6648931ff9e85fb85c41b2;hb=be40b55ee6886b1524e1a6b23fabfe6d03847f78;hp=ab1c484fbc2bcd4d63c768c53d673b9ae682ef91;hpb=45f83831984a48fefacb09f3754502f530fc158e;p=sonitus.git diff --git a/src/main/java/net/pterodactylus/sonitus/gui/PipelinePanel.java b/src/main/java/net/pterodactylus/sonitus/gui/PipelinePanel.java index ab1c484..133ec70 100644 --- a/src/main/java/net/pterodactylus/sonitus/gui/PipelinePanel.java +++ b/src/main/java/net/pterodactylus/sonitus/gui/PipelinePanel.java @@ -17,24 +17,30 @@ package net.pterodactylus.sonitus.gui; +import static javax.swing.BorderFactory.createCompoundBorder; +import static javax.swing.BorderFactory.createEmptyBorder; import static javax.swing.BorderFactory.createEtchedBorder; +import java.awt.BorderLayout; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; import java.util.Collection; -import java.util.List; +import java.util.EventListener; +import java.util.logging.Logger; import javax.swing.JLabel; import javax.swing.JPanel; +import javax.swing.event.EventListenerList; -import net.pterodactylus.sonitus.data.Controlled; -import net.pterodactylus.sonitus.data.Filter; +import net.pterodactylus.sonitus.data.ControlledComponent; +import net.pterodactylus.sonitus.data.Metadata; +import net.pterodactylus.sonitus.data.MetadataListener; import net.pterodactylus.sonitus.data.Pipeline; import net.pterodactylus.sonitus.data.Sink; import net.pterodactylus.sonitus.data.Source; -import com.google.common.collect.Lists; - /** * {@link JPanel} that displays all components of a {@link Pipeline}. * @@ -42,9 +48,15 @@ import com.google.common.collect.Lists; */ public class PipelinePanel extends JPanel { + /** The logger. */ + private static final Logger logger = Logger.getLogger(PipelinePanel.class.getName()); + /** The pipeline being displayed. */ private final Pipeline pipeline; + /** The component hover listeners. */ + private final EventListenerList componentHoverListeners = new EventListenerList(); + /** * Creates a new pipeline panel displaying the given pipeline. * @@ -58,6 +70,20 @@ public class PipelinePanel extends JPanel { } // + // LISTENER MANAGEMENT + // + + /** + * Adds the given component hover listener to this panel. + * + * @param componentHoverListener + * The component hover listener to add + */ + public void addComponentHoverListener(ComponentHoverListener componentHoverListener) { + componentHoverListeners.add(ComponentHoverListener.class, componentHoverListener); + } + + // // PRIVATE METHODS // @@ -68,16 +94,16 @@ public class PipelinePanel extends JPanel { /* count all sinks. */ int sinkCount = 0; - List sources = Lists.newArrayList(pipeline.source()); - while (!sources.isEmpty()) { - Collection sinks = pipeline.sinks(sources.remove(0)); - for (Sink sink : sinks) { - /* only count real sinks, everything else is filter. */ - if (sink instanceof Filter) { - sources.add((Filter) sink); - } else { - sinkCount++; - } + for (ControlledComponent component : pipeline.components()) { + if (!(component instanceof Source)) { + logger.finest(String.format("%s is not a Source, skipping.", component.name())); + sinkCount++; + continue; + } + Collection sinks = pipeline.sinks((Source) component); + logger.finest(String.format("%s has %d sinks: %s", component.name(), sinks.size(), sinks)); + if (sinks.isEmpty()) { + sinkCount++; } } @@ -88,13 +114,13 @@ public class PipelinePanel extends JPanel { } /* paint all components recursively. */ - addControlled(pipeline.source(), 0, 0, gridCellCount); + addControlled(pipeline.source(), 0, 0, gridCellCount, null); } /** * Displays the given component. * - * @param controlled + * @param controlledComponent * The component to add this panel. * @param level * The level at which to show the component (the source is level {@code 0}) @@ -103,28 +129,94 @@ public class PipelinePanel extends JPanel { * @param width * The width of the component in grid cells */ - private void addControlled(Controlled controlled, int level, int position, int width) { + private void addControlled(final ControlledComponent controlledComponent, int level, int position, int width, ControlledComponent parentComponent) { /* create a GUI component that displays the component. */ - JLabel sourceLabel = new JLabel(controlled.name()); - sourceLabel.setBorder(createEtchedBorder()); + JPanel componentPanel = createComponentPanel(controlledComponent, parentComponent); + componentPanel.addMouseListener(new MouseAdapter() { + + @Override + public void mouseEntered(MouseEvent mouseEvent) { + for (ComponentHoverListener componentHoverListener : componentHoverListeners.getListeners(ComponentHoverListener.class)) { + componentHoverListener.componentEntered(controlledComponent); + } + } + }); /* show component. */ - add(sourceLabel, new GridBagConstraints(position, level, width, 1, 1.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0)); + add(componentPanel, new GridBagConstraints(position, level, width, 1, 1.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0)); /* if the component does not have connected sinks, exit here. */ - if (!(controlled instanceof Source)) { + if (!(controlledComponent instanceof Source)) { + add(new JPanel(), new GridBagConstraints(position, 999, width, 1, 1.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0)); return; } /* iterate over the component’s sinks. */ - Collection sinks = pipeline.sinks((Source) controlled); - int sinkWidth = width / sinks.size(); - int sinkIndex = 0; - for (Sink connectedSink : sinks) { - /* distribute all sinks evenly below this source. */ - addControlled(connectedSink, level + 1, position + sinkIndex * sinkWidth, sinkWidth); - sinkIndex++; + Collection sinks = pipeline.sinks((Source) controlledComponent); + if (!sinks.isEmpty()) { + int sinkWidth = width / sinks.size(); + int sinkIndex = 0; + for (Sink connectedSink : sinks) { + /* distribute all sinks evenly below this source. */ + addControlled(connectedSink, level + 1, position + sinkIndex * sinkWidth, sinkWidth, controlledComponent); + sinkIndex++; + } } } + /** + * Creates a panel displaying a single component. + * + * @param controlledComponent + * The component to display + * @return The created panel + */ + private static JPanel createComponentPanel(final ControlledComponent controlledComponent, final ControlledComponent parentComponent) { + JPanel componentPanel = new JPanel(new BorderLayout(12, 12)); + componentPanel.setBorder(createCompoundBorder(createEtchedBorder(), createEmptyBorder(0, 4, 0, 3))); + componentPanel.add(new JLabel(controlledComponent.name()), BorderLayout.WEST); + final JLabel titleLabel = new JLabel(controlledComponent.metadata().title()); + titleLabel.setFont(titleLabel.getFont().deriveFont(titleLabel.getFont().getSize2D() * 0.8f)); + componentPanel.add(titleLabel, BorderLayout.EAST); + if (parentComponent != null) { + titleLabel.setVisible(!parentComponent.metadata().title().equals(controlledComponent.metadata().title())); + parentComponent.addMetadataListener(new MetadataListener() { + + @Override + public void metadataUpdated(ControlledComponent component, Metadata metadata) { + titleLabel.setText(metadata.title()); + titleLabel.setVisible(!controlledComponent.metadata().title().equals(metadata.title())); + } + }); + } + controlledComponent.addMetadataListener(new MetadataListener() { + + @Override + public void metadataUpdated(ControlledComponent component, Metadata metadata) { + titleLabel.setText(metadata.title()); + titleLabel.setVisible((parentComponent == null) || !parentComponent.metadata().title().equals(metadata.title())); + } + }); + return componentPanel; + } + + /** + * Interface for objects that want to be notified if the user moves the mouse + * cursor over a controlled component. + * + * @author David ‘Bombe’ Roden + */ + public static interface ComponentHoverListener extends EventListener { + + /** + * Notifies the listener that the mouse is now over the given controlled + * component. + * + * @param controlledComponent + * The controlled component now under the mouse + */ + void componentEntered(ControlledComponent controlledComponent); + + } + }