Newer
Older
democall3 / src / gui / processors / AbstractLabelProcessor.java
package gui.processors;

import constants.Constants;
import gui.QueuePanel;
import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.awt.event.MouseAdapter;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import javax.swing.JLabel;
import javax.swing.JPanel;

/**
 *
 * @author Mark
 */
public abstract class AbstractLabelProcessor {

   private final Color requestCol = Color.GREEN;
   private final Color regularCol = new JLabel().getBackground();
   private final Map<Integer, JLabel> labels = new ConcurrentHashMap<Integer, JLabel>();
//   protected final Collection<Integer> queue = new ConcurrentLinkedQueue<Integer> ();
   protected final Collection<Integer> queue = new LinkedHashSet<Integer>();

   public abstract MouseAdapter getMouseAdapter();

   public final void processLabels(final JPanel panel) {
      processPanel(panel);
   }

   private void processPanel(final JPanel panel) {
      for (Component component : panel.getComponents()) {

         if (component instanceof JLabel) {
            final JLabel label = (JLabel) component;
            try {
               // component must be opaque so the background color can be set
               label.setOpaque(true);
               final Integer id = Integer.valueOf(label.getText());
               labels.put(id, label);

               label.addMouseListener(this.getMouseAdapter());

            } catch (NumberFormatException ignored) {
               continue;
            }
         } else if (component instanceof JPanel) {
            // found a panel that might contain labels so recurse
            processPanel((JPanel) component);
         }
      }
   }

   public void resizeFonts(float newFontSize) {
      // there should always labels in this map so hopefully this next line doesn't cause issues
      Font newFont = labels.values().iterator().next().getFont().deriveFont(newFontSize);
      
      for (JLabel label : labels.values()) {
         label.setFont(newFont);
      }
      
      QueuePanel.getQueueLabel().setFont(newFont);
   }   
   
   public final void request(final int id) {
      synchronized (queue) {
         queue.add(id);

         final String queueStr = queue.toString();

         final JLabel label = labels.get(id);

         if (label != null) {
            label.setBackground(requestCol);
         }
         QueuePanel.getQueueLabel().setText(queueStr.substring(1, queueStr.length() - 1));
         
      }
         updateTutorClients(queue);
   }

   public final synchronized void cancel(final int id) {
      synchronized (queue) {
         queue.remove(id);

         final String queueStr = queue.toString();

         QueuePanel.getQueueLabel().setText(queueStr.substring(1, queueStr.length() - 1));

         final JLabel label = labels.get(id);

         if (label != null) {
            label.setBackground(regularCol);
         }
      }
         updateTutorClients(queue);         
   }

   public final Collection<Integer> getQueue() {
      synchronized (queue) {
         // Creating a copy of queue to prevent ConcurrentModification errors.
         // This only works because queue is locked by the sync block
         return new ArrayList<Integer>(queue);
      }
   }

   private void updateTutorClients(Collection<Integer> queue1) {
      Iterator<ObjectOutputStream> it = Constants.PERSISTENT_SOCKETS.iterator();
      while (it.hasNext()) {
         try {
            ObjectOutputStream oos = it.next();
            oos.reset(); // necessary since if you send the same object twice some "optimisations" happen causing the client to see cached versions of the object
            oos.writeObject(queue);
            oos.flush();
            System.out.println(queue);
         } catch (IOException ex) {
            it.remove();
         }
      }
   }
}