content: package io.github.rowak.nanoleafdesktop.ui.panel;
  
  import java.awt.Color;
  import java.awt.Font;
  import java.awt.event.MouseAdapter;
  import java.awt.event.MouseEvent;
  import java.io.IOException;
  import java.util.ArrayList;
  import java.util.List;
  
  import javax.swing.DefaultListModel;
  import javax.swing.JList;
  import javax.swing.JScrollPane;
  import javax.swing.border.LineBorder;
  import javax.swing.border.TitledBorder;
  
  import io.github.rowak.nanoleafapi.Effect;
  import io.github.rowak.nanoleafapi.NanoleafDevice;
  import io.github.rowak.nanoleafapi.NanoleafException;
  import io.github.rowak.nanoleafapi.NanoleafGroup;
  import io.github.rowak.nanoleafdesktop.Main;
  import io.github.rowak.nanoleafdesktop.models.BasicEffect;
  import io.github.rowak.nanoleafdesktop.tools.BasicEffects;
  import io.github.rowak.nanoleafdesktop.tools.UIConstants;
  import io.github.rowak.nanoleafdesktop.ui.dialog.LoadingSpinner;
  import io.github.rowak.nanoleafdesktop.ui.dialog.TextDialog;
  import io.github.rowak.nanoleafdesktop.ui.menu.EffectOptionsMenu;
  import io.github.rowak.nanoleafdesktop.ui.panel.panelcanvas.PanelCanvas;
  import io.github.rowak.nanoleafdesktop.ui.scrollbar.ModernScrollBarUI;
  
  public class EffectsPanel extends JScrollPane {
  	
  	private String label;
  	private NanoleafGroup group;
  	private Main parent;
  	private PanelCanvas canvas;
  	private JList<String> effects;
  	private DefaultListModel<String> model;
  	
  	public EffectsPanel(String label, Main parent,
  			NanoleafGroup group, PanelCanvas canvas) {
  		this.label = label;
  		this.parent = parent;
  		this.group = group;
  		this.canvas = canvas;
  		init();
  	}
  	
  	public void addEffects(List<String> effects) {
  		for (String effect : effects) {
  			if (!model.contains(effect)) {
  				model.addElement(effect);
  			}
  		}
  	}
  	
  	public void addEffect(String effect) {
  		if (!model.contains(effect)) {
  			model.addElement(effect);
  		}
  	}
  	
  	public void removeEffect(String effect) {
  		if (model.contains(effect)) {
  			model.removeElement(effect);
  		}
  	}
  	
  	public void setAuroras(NanoleafGroup group) {
  		this.group = group;
  	}
  	
  	public void clearEffects() {
  		model.clear();
  	}
  	
  	public DefaultListModel<String> getModel() {
  		return model;
  	}
  	
  	public JList<String> getList() {
  		return effects;
  	}
  	
  	private void init() {
  		getVerticalScrollBar().setUI(new ModernScrollBarUI());
  		getHorizontalScrollBar().setUI(new ModernScrollBarUI());
  		setBackground(UIConstants.darkBackground);
  		setForeground(UIConstants.textPrimary);
  		setBorder(new TitledBorder(new LineBorder(Color.GRAY),
  				label, TitledBorder.LEFT, TitledBorder.TOP, null, Color.WHITE));
  		((TitledBorder)getBorder())
  			.setTitleFont(new Font("Tahoma", Font.BOLD, 22));
  		
  		model = new DefaultListModel<String>();
  		effects = new JList<String>(model);
  		effects.setBackground(UIConstants.darkBackground);
  		effects.setForeground(UIConstants.textPrimary);
  		effects.setFont(new Font("Tahoma", Font.PLAIN, 19));
  		effects.addMouseListener(new MouseAdapter() {
  			@Override
  			public void mouseClicked(MouseEvent e) {
  				JList<String> list = (JList<String>)e.getSource();
  				parent.unselectAllExcept(EffectsPanel.this);
  				if (e.getButton() == MouseEvent.BUTTON1) {
  					if (label.equals("Basic Effects")) {
  						setBasicEffectForDevices(list.getSelectedValue());
  					}
  					else {
  						setEffectForDevices(list.getSelectedValue());
  					}
  				}
  				else if (e.getButton() == MouseEvent.BUTTON3) {
  					createEffectOptionsMenu();
  				}
  			}
  		});
  		
  		LoadingSpinner regEffectsSpinner =
  				new LoadingSpinner(UIConstants.darkBackground);
  		setViewportView(regEffectsSpinner);
  	}
  	
  	private void setEffectForDevices(String effectName) {
  		try {
  			Effect effect = null;
  			List<NanoleafDevice> uninstalled = new ArrayList<NanoleafDevice>();
  			for (NanoleafDevice device : group.getDevices().values()) {
  				try {
  					Effect tempEffect = device.getEffect(effectName);
  					effect = tempEffect;
  					device.setEffect(effectName);
  				}
  				catch (Exception e) {
  					uninstalled.add(device);
  				}
  			}
  			for (NanoleafDevice device : uninstalled) {
  				device.displayEffect(effect);
  			}
  			canvas.checkAuroraStateForAll();
  			parent.loadStateComponents();
  		}
  		catch (NanoleafException | IOException e) {
  			e.printStackTrace();
  			new TextDialog(parent,
  					"The requested action could not be completed. " +
  					"Please try again.").setVisible(true);
  		}
  	}
  	
  	private void setBasicEffectForDevices(String effectName) {
  		try {
  			List<BasicEffect> basicEffects = BasicEffects.getBasicEffects();
  			for (BasicEffect ef : basicEffects) {
  				if (ef.getName().equals(effectName)) {
  					group.setHueAsync(ef.getHue(), null);
  					group.setSaturationAsync(ef.getSaturation(), null);
  					canvas.checkAuroraStateForAll();
  					parent.loadStateComponents();
  					break;
  				}
  			}
  		}
  		catch (NanoleafException | IOException e) {
  			e.printStackTrace();
  			new TextDialog(parent,
  					"The requested action could not be completed. " +
  					"Please try again.").setVisible(true);
  		}
  	}
  	
  	private void createEffectOptionsMenu() {
  		new EffectOptionsMenu(EffectsPanel.this,
  				label, group, parent);
  	}
  }
  