package org.micromanager.pipelineUI;

import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.plaf.basic.BasicArrowButton;

import java.util.List;

import mmcorej.TaggedImage;

import net.miginfocom.swing.MigLayout;

import org.micromanager.api.DataProcessor;
import org.micromanager.api.ScriptInterface;
import org.micromanager.utils.ReportingUtils;

public class ProcessorPanel extends javax.swing.JPanel {
   // The DataProcessor we are displaying controls for. 
   DataProcessor<TaggedImage> processor_;
   // We need access to the ScriptInterface to enable/disable the Processor.
   ScriptInterface gui_;
   // Checkbox for enabling/disabling the Processor.
   javax.swing.JCheckBox activeBox_;

   // Preferred width of the panel.
   public static int preferredWidth = 400;
   // Preferred height of the panel.
   public static int preferredHeight = 100;

   ProcessorPanel(String name, DataProcessor<TaggedImage> processor,
         ScriptInterface gui) {
      // The central element is the processor name, i.e. the only element
      // of variable size. We want it to be of fixed size so that elements
      // to its right are properly-aligned.
      super(new net.miginfocom.swing.MigLayout("wrap 3", 
               "[][200!][]"));
      processor_ = processor;
      gui_ = gui;

      activeBox_ = new javax.swing.JCheckBox(
            "Active:", processor.getIsEnabled());
      activeBox_.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent e) {
            toggleActive();
         }
      });
      add(activeBox_);

      JLabel label = new JLabel(name);
      add(label);

      // Move the processor up (earlier) in the pipeline.
      javax.swing.plaf.basic.BasicArrowButton upButton = new javax.swing.plaf.basic.BasicArrowButton(javax.swing.plaf.basic.BasicArrowButton.NORTH);
      upButton.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent e) {
            moveProcessor(-1);
         }
      });
      add(upButton);

      JButton configButton = new JButton("Configure");
      configButton.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent e) {
            processor_.makeConfigurationGUI();
         }
      });
      add(configButton);

      JButton deleteButton = new JButton("Delete");
      deleteButton.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent e) {
            gui_.removeImageProcessor(processor_);
         }
      });
      add(deleteButton);

      // Move the processor down (later) in the pipeline.
      javax.swing.plaf.basic.BasicArrowButton downButton = new javax.swing.plaf.basic.BasicArrowButton(
            javax.swing.plaf.basic.BasicArrowButton.SOUTH);
      downButton.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent e) {
            moveProcessor(1);
         }
      });
      add(downButton);
   }

   // Overriding this method so that layout of these panels works properly.
   public java.awt.Dimension getPreferredSize() {
      return new java.awt.Dimension(
            ProcessorPanel.preferredWidth, ProcessorPanel.preferredHeight);
   }

   // Toggle whether or not this Processor belongs in the pipeline.
   private void toggleActive() {
      processor_.setEnabled(activeBox_.isSelected());
   }

   // Adjust the processor's position in the pipeline by the given offset.
   private void moveProcessor(int offset) {
      List<DataProcessor<TaggedImage>> pipeline = gui_.getImageProcessorPipeline();
      // NB for some reason using List.indexOf doesn't work here, so we 
      // manually scan the list for a matching Processor.
      int curIndex = 0;
      for (DataProcessor<TaggedImage> altProcessor : pipeline) {
         if (altProcessor.hashCode() == processor_.hashCode()) {
            break;
         }
         curIndex++;
      }
      if (curIndex == pipeline.size()) {
         ReportingUtils.logError("Tried to move a processor that isn't actually in the pipeline!");
         return;
      }
      int targetIndex = curIndex + offset;
      if (targetIndex < 0 || targetIndex >= pipeline.size()) {
         // Processor is already at the end of the pipeline and can't be 
         // moved further.
         return;
      }
      pipeline.remove(processor_);
      pipeline.add(targetIndex, processor_);
      gui_.setImageProcessorPipeline(pipeline);
   }
}

@@ -1839,39 +1839,16 @@
 .%0A      
-javax.swing.plaf.basic.
 BasicArr
@@ -1875,71 +1875,25 @@
 new 
-javax.swing.plaf.basic.BasicArrowButton(javax.swing.plaf.basic.
+BasicArrowButton(
 Basi
@@ -2688,39 +2688,16 @@
 .%0A      
-javax.swing.plaf.basic.
 BasicArr
@@ -2726,84 +2726,25 @@
 new 
-javax.swing.plaf.basic.BasicArrowButton(%0A            javax.swing.plaf.basic.
+BasicArrowButton(
 Basi

Be less pedantic about specifying the path to a class.