diff --git a/Builds/Linux/Makefile b/Builds/Linux/Makefile
index 73471e695a24df8fa0f5adbd3a8841dcf3b02bf5..f3f47f4496a6e30d5ab7217cd302b6adc1c26d38 100644
--- a/Builds/Linux/Makefile
+++ b/Builds/Linux/Makefile
@@ -85,6 +85,7 @@ OBJECTS := \
   $(OBJDIR)/SpikeDetector_300d85e7.o \
   $(OBJDIR)/AudioNode_94606ff3.o \
   $(OBJDIR)/EventNode_95c842b7.o \
+  $(OBJDIR)/ChannelSelector_c1430874.o \
   $(OBJDIR)/ParameterEditor_91f62ae8.o \
   $(OBJDIR)/SpikeDisplayEditor_e1812c1.o \
   $(OBJDIR)/VisualizerEditor_3672b003.o \
@@ -357,6 +358,11 @@ $(OBJDIR)/EventNode_95c842b7.o: ../../Source/Processors/EventNode.cpp
 	@echo "Compiling EventNode.cpp"
 	@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
 
+$(OBJDIR)/ChannelSelector_c1430874.o: ../../Source/Processors/Editors/ChannelSelector.cpp
+	-@mkdir -p $(OBJDIR)
+	@echo "Compiling ChannelSelector.cpp"
+	@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
+
 $(OBJDIR)/ParameterEditor_91f62ae8.o: ../../Source/Processors/Editors/ParameterEditor.cpp
 	-@mkdir -p $(OBJDIR)
 	@echo "Compiling ParameterEditor.cpp"
diff --git a/Builds/MacOSX/open-ephys.xcodeproj/project.pbxproj b/Builds/MacOSX/open-ephys.xcodeproj/project.pbxproj
index 9681d71e862fefdd1eb99f9d307ca8a1832f6db3..1d6614e0067b52ab825cb1b73a8c92eb543ac83f 100644
--- a/Builds/MacOSX/open-ephys.xcodeproj/project.pbxproj
+++ b/Builds/MacOSX/open-ephys.xcodeproj/project.pbxproj
@@ -59,6 +59,7 @@
 		4BE0DDA01B73223EF0BD934A = { isa = PBXBuildFile; fileRef = 3DD0741FCFBC7563EC722D9B; };
 		08B501E0D7764C6B613AF529 = { isa = PBXBuildFile; fileRef = B7750B27E4F3748ECCCCF69D; };
 		9CBA3837CC8CAA03A03F2D9C = { isa = PBXBuildFile; fileRef = FA57CE4F63FF1592D6B3F9B5; };
+		BCB6C021A03F0AB0248C7F8A = { isa = PBXBuildFile; fileRef = 51D2678E9F30DC261CCB61B0; };
 		632C915D01C42D27E828BFA9 = { isa = PBXBuildFile; fileRef = 47ECF9384C1D27EB2FBEBF9E; };
 		DD22A06702F4CF995893DD5C = { isa = PBXBuildFile; fileRef = F0B09605D4108F0F94EF3B57; };
 		F4CEF74DDCD7EFA0891249B5 = { isa = PBXBuildFile; fileRef = 9A3976537C96B39716B5312D; };
@@ -264,6 +265,8 @@
 		12866D44BE115E8837468F48 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AudioNode.h; path = ../../Source/Processors/AudioNode.h; sourceTree = SOURCE_ROOT; };
 		FA57CE4F63FF1592D6B3F9B5 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = EventNode.cpp; path = ../../Source/Processors/EventNode.cpp; sourceTree = SOURCE_ROOT; };
 		32163C956C8A6F5C1DD7FE7F = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = EventNode.h; path = ../../Source/Processors/EventNode.h; sourceTree = SOURCE_ROOT; };
+		51D2678E9F30DC261CCB61B0 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = ChannelSelector.cpp; path = ../../Source/Processors/Editors/ChannelSelector.cpp; sourceTree = SOURCE_ROOT; };
+		1A64B7009173729093BA3D96 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ChannelSelector.h; path = ../../Source/Processors/Editors/ChannelSelector.h; sourceTree = SOURCE_ROOT; };
 		47ECF9384C1D27EB2FBEBF9E = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = ParameterEditor.cpp; path = ../../Source/Processors/Editors/ParameterEditor.cpp; sourceTree = SOURCE_ROOT; };
 		07363B9FB8F988D45C4F0FE2 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ParameterEditor.h; path = ../../Source/Processors/Editors/ParameterEditor.h; sourceTree = SOURCE_ROOT; };
 		F0B09605D4108F0F94EF3B57 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = SpikeDisplayEditor.cpp; path = ../../Source/Processors/Editors/SpikeDisplayEditor.cpp; sourceTree = SOURCE_ROOT; };
@@ -501,6 +504,8 @@
 				0C5335B0E57C9DC92FC57E5F,
 				7738F51AE0EC63D76EE0F761 ); name = Visualization; sourceTree = "<group>"; };
 		953CC35B9116404D6AA8D1C7 = { isa = PBXGroup; children = (
+				51D2678E9F30DC261CCB61B0,
+				1A64B7009173729093BA3D96,
 				47ECF9384C1D27EB2FBEBF9E,
 				07363B9FB8F988D45C4F0FE2,
 				F0B09605D4108F0F94EF3B57,
@@ -758,6 +763,7 @@
 				4BE0DDA01B73223EF0BD934A,
 				08B501E0D7764C6B613AF529,
 				9CBA3837CC8CAA03A03F2D9C,
+				BCB6C021A03F0AB0248C7F8A,
 				632C915D01C42D27E828BFA9,
 				DD22A06702F4CF995893DD5C,
 				F4CEF74DDCD7EFA0891249B5,
diff --git a/Source/Processors/Editors/ChannelSelector.cpp b/Source/Processors/Editors/ChannelSelector.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b8f2d8f14df6f0ab7ab180b9f11862868db4e56e
--- /dev/null
+++ b/Source/Processors/Editors/ChannelSelector.cpp
@@ -0,0 +1,548 @@
+/*
+    ------------------------------------------------------------------
+
+    This file is part of the Open Ephys GUI
+    Copyright (C) 2012 Open Ephys
+
+    ------------------------------------------------------------------
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "ChannelSelector.h"
+#include <math.h>
+
+#include "../RecordNode.h"
+#include "../AudioNode.h"
+
+ChannelSelector::ChannelSelector(bool createButtons, Font& titleFont_) :
+	isNotSink(createButtons), titleFont(titleFont_), offsetLR(0), offsetUD(0),
+	moveRight(false), moveLeft(false), desiredOffset(0)
+{
+
+	if (createButtons)
+	{
+		audioButton = new EditorButton("A", titleFont);
+	    audioButton->addListener(this);
+	    addAndMakeVisible(audioButton);
+
+	 	recordButton = new EditorButton("R", titleFont);
+		recordButton->addListener(this);
+		addAndMakeVisible(recordButton);
+
+		paramsButton = new EditorButton("P", titleFont);
+		paramsButton->addListener(this);
+		addAndMakeVisible(paramsButton);
+		
+		paramsButton->setToggleState(true, false);
+
+		audioButtons.clear();
+		recordButtons.clear();
+	}	
+
+
+	parameterOffset = 0;//
+	recordOffset = getDesiredWidth();
+	audioOffset = getDesiredWidth()*2;
+
+	parameterButtons.clear();
+
+	allButton = new EditorButton("all", titleFont);
+	allButton->addListener(this);
+	addAndMakeVisible(allButton);
+
+	noneButton = new EditorButton("none", titleFont);
+	noneButton->addListener(this);
+	addAndMakeVisible(noneButton);
+
+}
+
+ChannelSelector::~ChannelSelector()
+{
+	deleteAllChildren();
+
+}
+
+void ChannelSelector::paint(Graphics& g)
+{
+	ColourGradient grad1 = ColourGradient(Colours::black.withAlpha(0.8f),0.0,0.0,
+										  Colours::black.withAlpha(0.1f),0.0,25.0f,
+										  false);
+	g.setGradientFill(grad1);
+	g.fillRect(0, 15, getWidth()-1, getHeight()-30);
+
+	ColourGradient grad2 = ColourGradient(Colours::black.withAlpha(0.2f),0.0,0.0,
+										  Colours::black.withAlpha(0.0f),5.0f,0.0f,
+										  false);
+	g.setGradientFill(grad2);
+	g.fillRect(0, 15, getWidth()-1, getHeight()-30);
+
+	ColourGradient grad3 = ColourGradient(Colours::black.withAlpha(0.2f),(float) getDesiredWidth(),0.0,
+										  Colours::black.withAlpha(0.0f),(float) getDesiredWidth()-5.0f,0.0f,
+										  false);
+	g.setGradientFill(grad3);
+	g.fillRect(0, 15, getWidth()-1, getHeight()-30);
+}
+
+void ChannelSelector::setNumChannels(int numChans)
+{
+
+	int difference = numChans - parameterButtons.size();
+
+
+	std::cout << difference << " buttons needed." << std::endl;
+
+	if (difference > 0)
+	{
+		for (int n = 0; n < difference; n++)
+		{
+			addButton();
+		}
+	} else if (difference < 0)
+	{
+		for (int n = 0; n < -difference; n++)
+		{
+			removeButton();
+		}
+	}
+
+	refreshButtonBoundaries();
+
+}
+
+void ChannelSelector::refreshButtonBoundaries()
+{
+
+	int nColumns = 8;
+	int columnWidth = getDesiredWidth()/(nColumns + 1);
+	int rowHeight = 14;
+	int topOffset = 20;
+
+	for (int i = 0; i < parameterButtons.size(); i++)
+	{
+		parameterButtons[i]->setBounds(columnWidth/2 + offsetLR +
+									   columnWidth*((i)%nColumns),
+									   floor((i)/nColumns)*rowHeight+offsetUD + topOffset,
+									   columnWidth, rowHeight);
+
+		if (isNotSink)
+		{
+			recordButtons[i]->setBounds(columnWidth/2 + offsetLR +
+									   columnWidth*((i)%nColumns) - getDesiredWidth(),
+									   floor((i)/nColumns)*rowHeight+offsetUD + topOffset,
+									   columnWidth, rowHeight);
+			audioButtons[i]->setBounds(columnWidth/2 + offsetLR +
+									   columnWidth*((i)%nColumns) -
+									   	getDesiredWidth()*2,
+									   floor((i)/nColumns)*rowHeight+offsetUD + topOffset,
+									   columnWidth, rowHeight);
+		}
+
+	}
+
+	if (isNotSink)
+	{
+		int w = getWidth()/3;
+		int h = 15;
+
+		audioButton->setBounds(0, 0, w, h);
+		recordButton->setBounds(w, 0, w, h);
+		paramsButton->setBounds(w*2, 0, w, h);
+
+	}
+
+	allButton->setBounds(0, getHeight()-15, getWidth()/2, 15);
+	noneButton->setBounds(getWidth()/2, getHeight()-15, getWidth()/2, 15);
+
+}
+
+void ChannelSelector::resized()
+{
+	refreshButtonBoundaries();
+}
+
+void ChannelSelector::timerCallback()
+{
+
+	std::cout << desiredOffset - offsetLR << std::endl;
+
+	if (offsetLR != desiredOffset)
+	{
+		if (desiredOffset - offsetLR > 0)
+		{
+			offsetLR += 5;
+		} else {
+			offsetLR -= 5;
+		}
+
+	} else {
+		stopTimer();
+	}
+
+	refreshButtonBoundaries();
+
+}
+
+void ChannelSelector::addButton()
+{
+
+	int size = parameterButtons.size();
+
+	ChannelSelectorButton* b = new ChannelSelectorButton(size+1, PARAMETER, titleFont);
+	parameterButtons.add(b);
+	addAndMakeVisible(b);
+	b->setToggleState(true, false);
+	b->addListener(this);
+
+	if (isNotSink)
+	{
+		ChannelSelectorButton* br = new ChannelSelectorButton(size+1, RECORD, titleFont);
+		recordButtons.add(br);
+		addAndMakeVisible(br);
+		br->addListener(this);
+
+		ChannelSelectorButton* ba = new ChannelSelectorButton(size+1, AUDIO, titleFont);
+		audioButtons.add(ba);
+		addAndMakeVisible(ba);
+		ba->addListener(this);
+	}
+}
+
+void ChannelSelector::removeButton()
+{
+	int size = parameterButtons.size();
+
+	ChannelSelectorButton* b = parameterButtons.remove(size-1);
+	removeChildComponent(b);
+	deleteAndZero(b);
+
+	if (isNotSink)
+	{
+		ChannelSelectorButton* br = recordButtons.remove(size-1);
+		removeChildComponent(br);
+		deleteAndZero(br);
+
+		ChannelSelectorButton* ba = audioButtons.remove(size-1);
+		removeChildComponent(ba);
+		deleteAndZero(ba);
+	}
+}
+
+Array<int> ChannelSelector::getActiveChannels()
+{
+	Array<int> a;
+	for (int i = 0; i < parameterButtons.size(); i++)
+	{
+		if (parameterButtons[i]->getToggleState())
+			a.add(i);
+	}
+
+	return a;
+}
+
+bool ChannelSelector::getRecordStatus(int chan)
+{
+
+	return recordButtons[chan]->getToggleState();
+
+}
+
+
+int ChannelSelector::getDesiredWidth()
+{
+	return 150;
+}
+
+void ChannelSelector::buttonClicked(Button* button)
+{
+	//checkChannelSelectors();
+	if (button == paramsButton)
+	{
+		// make sure param buttons are visible
+		allButton->setState(true);
+		desiredOffset = parameterOffset;
+		startTimer(5);
+		return;
+	} else if (button == audioButton)
+	{
+		// make sure audio buttons are visible
+		allButton->setState(false);
+			
+		desiredOffset = audioOffset;
+		startTimer(5);
+		return;
+	} else if (button == recordButton)
+	{
+		// make sure record buttons are visible;
+		allButton->setState(true);
+		desiredOffset = recordOffset;
+		startTimer(5);
+		return;
+	} 
+	else if (button == allButton)	
+	{
+		// select all active buttons
+		if (offsetLR == recordOffset)
+		{
+			
+
+			for (int i = 0; i < recordButtons.size(); i++)
+			{
+				recordButtons[i]->setToggleState(true, true);
+			}
+		} else if (offsetLR == parameterOffset)
+		{
+			
+
+			for (int i = 0; i < parameterButtons.size(); i++)
+			{
+				parameterButtons[i]->setToggleState(true, true);
+			}
+		} else if (offsetLR == audioOffset)
+		{
+			// do nothing--> button is disabled
+		}
+	} else if (button == noneButton)
+	{
+		// deselect all active buttons
+		if (offsetLR == recordOffset)
+		{
+			for (int i = 0; i < recordButtons.size(); i++)
+			{
+				recordButtons[i]->setToggleState(false, true);
+			}
+		} else if (offsetLR == parameterOffset)
+		{
+			for (int i = 0; i < parameterButtons.size(); i++)
+			{
+				parameterButtons[i]->setToggleState(false, true);
+			}
+		} else if (offsetLR == audioOffset)
+		{
+			for (int i = 0; i < audioButtons.size(); i++)
+			{
+				audioButtons[i]->setToggleState(false, true);
+			}
+		}
+	} else {
+
+		ChannelSelectorButton* b = (ChannelSelectorButton*) button;
+
+		if (b->getType() == AUDIO)
+		{
+			// get audio node, and inform it of the change
+			//getProcessorGraph()->getAudioNode()->setChannel();
+			//getProcessorGraph()->getAudioNode()->setParameter();
+
+		} else if (b->getType() == RECORD)
+		{
+			// get record node, and inform it of the change
+			//getProcessorGraph()->getRecordNode()->setChannel();
+			//getProcessorGraph()->getRecordNode()->setParameter();
+		} else {
+			// do nothing
+		}
+
+	}
+
+}
+
+
+///////////// BUTTONS //////////////////////
+
+
+EditorButton::EditorButton(const String& name, Font& f) : Button(name) 
+{
+
+	isEnabled = true;
+
+	buttonFont = f;
+	buttonFont.setHeight(10);
+
+	if (!getName().equalsIgnoreCase("all") && !getName().equalsIgnoreCase("none"))
+	{
+    	setRadioGroupId(999);
+    	setClickingTogglesState(true);
+    }
+
+    selectedGrad = ColourGradient(Colour(240,179,12),0.0,0.0,
+										 Colour(207,160,33),0.0, 20.0f,
+										 false);
+    selectedOverGrad = ColourGradient(Colour(209,162,33),0.0, 5.0f,
+										 Colour(190,150,25),0.0, 0.0f,
+										 false);
+    neutralGrad = ColourGradient(Colour(220,220,220),0.0,0.0,
+										 Colour(170,170,170),0.0, 20.0f,
+										 false);
+    neutralOverGrad = ColourGradient(Colour(180,180,180),0.0,5.0f,
+										 Colour(150,150,150),0.0, 0.0,
+										 false);
+
+
+}
+
+void EditorButton::resized()
+{
+    float radius = 5.0f;
+    float width = (float) getWidth();
+    float height = (float) getHeight();
+
+    if (getName().equalsIgnoreCase("A"))
+	{
+		//outlinePath.startNewSubPath(0, height);
+		outlinePath.lineTo(0, radius);
+		outlinePath.addArc(0, 0, radius*2, radius*2, 1.5*double_Pi, 2.0*double_Pi );
+
+		outlinePath.lineTo(width, 0);//getHeight());
+
+		outlinePath.lineTo(width, height);
+
+		outlinePath.lineTo(0, height);
+		//outlinePath.addArc(0, getHeight()-radius*2, radius*2, radius*2, double_Pi, 1.5*double_Pi);
+		//outlinePath.lineTo(0, radius);
+		outlinePath.closeSubPath();
+
+	} else if (getName().equalsIgnoreCase("P"))
+	{
+		//outlinePath.startNewSubPath(0, 0);
+
+		outlinePath.lineTo(width-radius, 0);
+	
+		outlinePath.addArc(width-radius*2, 0, radius*2, radius*2, 0, 0.5*double_Pi);
+
+		outlinePath.lineTo(getWidth(), height);
+
+		//outlinePath.addArc(getWidth()-radius*2, getHeight()-radius*2, radius*2, radius*2, 0.5*double_Pi, double_Pi);
+
+		outlinePath.lineTo(0, height);
+		outlinePath.lineTo(0, 0);
+		//outlinePath.closeSubPath();
+
+
+	} else if (getName().equalsIgnoreCase("R"))
+	{
+
+		outlinePath.addRectangle(0,0,getWidth(),getHeight());
+
+	} else if (getName().equalsIgnoreCase("all"))
+	{
+
+		//outlinePath.startNewSubPath(0, 0);
+
+		outlinePath.lineTo(width, 0);
+	
+		//outlinePath.addArc(width-radius*2, 0, radius*2, radius*2, 0, 0.5*double_Pi);
+
+		outlinePath.lineTo(width, height);
+
+		//outlinePath.addArc(getWidth()-radius*2, getHeight()-radius*2, radius*2, radius*2, 0.5*double_Pi, double_Pi);
+
+		outlinePath.lineTo(radius, height);
+		outlinePath.addArc(0, height-radius*2, radius*2, radius*2, double_Pi, 1.5*double_Pi);
+
+		outlinePath.lineTo(0, 0);
+		//outlinePath.closeSubPath();
+
+	} else if (getName().equalsIgnoreCase("none"))
+	{
+
+		//outlinePath.startNewSubPath(0, 0);
+
+		outlinePath.lineTo(width, 0);
+	
+		//outlinePath.addArc(width-radius*2, 0, radius*2, radius*2, 0, 0.5*double_Pi);
+
+		outlinePath.lineTo(width, height-radius);
+
+		outlinePath.addArc(width-radius*2, height-radius*2, radius*2, radius*2, 0.5*double_Pi, double_Pi);
+
+		outlinePath.lineTo(0, height);
+
+		outlinePath.lineTo(0, 0);
+		//outlinePath.closeSubPath();
+
+	}
+
+}
+
+
+void EditorButton::paintButton(Graphics &g, bool isMouseOver, bool isButtonDown)
+{
+
+	g.setColour(Colours::grey);
+	g.fillPath(outlinePath);
+
+	 if (getToggleState())
+     {
+     	if (isMouseOver && isEnabled)
+     		g.setGradientFill(selectedOverGrad);
+        else
+        	g.setGradientFill(selectedGrad);
+     } else {
+         if (isMouseOver && isEnabled)
+         	g.setGradientFill(neutralOverGrad);
+        else
+        	g.setGradientFill(neutralGrad);
+     }
+
+	AffineTransform a = AffineTransform::scale(0.98f, 0.94f, float(getWidth())/2.0f,
+												float(getHeight())/2.0f);
+	g.fillPath(outlinePath, a);
+
+	buttonFont.setHeight(12.0f);
+	int stringWidth = buttonFont.getStringWidth(getName());
+
+	g.setFont(buttonFont);
+
+	if (isEnabled)
+		g.setColour(Colours::darkgrey);
+	else
+		g.setColour(Colours::lightgrey);
+
+	g.drawSingleLineText(getName(), getWidth()/2 - stringWidth/2, 10);
+
+}
+
+
+ChannelSelectorButton::ChannelSelectorButton(int num_, int type_, Font& f) : Button("name") 
+{
+	num = num_;
+	type = type_;
+
+    setClickingTogglesState(true);
+
+    buttonFont = f;
+    buttonFont.setHeight(10);
+}
+
+
+void ChannelSelectorButton::paintButton(Graphics &g, bool isMouseOver, bool isButtonDown)
+{
+    if (getToggleState() == true)
+        g.setColour(Colours::orange);
+    else 
+        g.setColour(Colours::darkgrey);
+
+    if (isMouseOver)
+        g.setColour(Colours::white);
+
+    // g.fillRect(0,0,getWidth(),getHeight());
+
+    g.setFont(buttonFont);
+
+    // g.drawRect(0,0,getWidth(),getHeight(),1.0);
+
+    g.drawText(String(num),0,0,getWidth(),getHeight(),Justification::centred,true);
+}
diff --git a/Source/Processors/Editors/ChannelSelector.h b/Source/Processors/Editors/ChannelSelector.h
new file mode 100644
index 0000000000000000000000000000000000000000..ba44384b7c27df660daf122da9888e63a2f2c4ba
--- /dev/null
+++ b/Source/Processors/Editors/ChannelSelector.h
@@ -0,0 +1,161 @@
+/*
+    ------------------------------------------------------------------
+
+    This file is part of the Open Ephys GUI
+    Copyright (C) 2012 Open Ephys
+
+    ------------------------------------------------------------------
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef __CHANNELSELECTOR_H_68124E35__
+#define __CHANNELSELECTOR_H_68124E35__
+
+#include "../../../JuceLibraryCode/JuceHeader.h"
+#include "GenericEditor.h"
+#include "../../AccessClass.h"
+
+#include <stdio.h>
+
+/**
+  
+  Automatically creates an interactive editor for selecting channels
+
+  @see GenericEditor
+
+*/
+
+class ChannelSelectorButton;
+class EditorButton;
+
+class ChannelSelector : public Component,
+						public Button::Listener,
+						public AccessClass,
+						public Timer
+{
+public:
+
+	ChannelSelector(bool createButtons, Font& titleFont);
+	~ChannelSelector();
+
+	void buttonClicked(Button* button);
+
+	Array<int> getActiveChannels();
+
+	void setNumChannels(int);
+
+	bool getRecordStatus(int chan);
+
+	int getDesiredWidth();
+
+private:
+
+	EditorButton* audioButton;
+	EditorButton* recordButton;
+	EditorButton* paramsButton;
+	EditorButton* allButton;
+	EditorButton* noneButton;
+
+	Array<ChannelSelectorButton*> parameterButtons;
+	Array<ChannelSelectorButton*> audioButtons;
+	Array<ChannelSelectorButton*> recordButtons;
+
+	bool isNotSink;
+	bool moveRight;
+	bool moveLeft;
+
+	int offsetLR;
+	int offsetUD;
+
+	int parameterOffset;
+	int audioOffset;
+	int recordOffset;
+
+	int desiredOffset;
+
+	void resized();
+
+	void addButton();
+	void removeButton();
+	void refreshButtonBoundaries();
+
+	void timerCallback();
+
+	void paint(Graphics& g);
+
+	Font& titleFont;
+
+	enum {AUDIO, RECORD, PARAMETER};
+
+};
+
+
+class EditorButton : public Button
+{
+public:
+	EditorButton(const String& name, Font& f);
+	~EditorButton() {}
+
+	void setState(bool state) 
+	{
+		isEnabled = state;
+
+		if (!state)
+		{
+			removeListener((Button::Listener*) getParentComponent());
+		} else {
+			addListener((Button::Listener*) getParentComponent());
+		}
+
+		repaint();
+	}
+
+private:
+	void paintButton(Graphics& g, bool isMouseOver, bool isButtonDown);
+	
+	void resized();
+
+	Path outlinePath;
+
+	
+
+	int type;
+	Font buttonFont;
+
+	bool isEnabled;
+
+	ColourGradient selectedGrad, selectedOverGrad, neutralGrad, neutralOverGrad;
+};
+
+class ChannelSelectorButton : public Button
+{
+public:
+	ChannelSelectorButton(int num, int type, Font& f);
+	~ChannelSelectorButton() {}
+
+	int getType() {return type;}
+	int getChannel() {return num;}
+
+private:
+	void paintButton(Graphics& g, bool isMouseOver, bool isButtonDown);
+	
+	int type;
+	int num;
+	Font buttonFont;
+};
+
+
+#endif  // __CHANNELSELECTOR_H_68124E35__
diff --git a/Source/Processors/Editors/EventNodeEditor.cpp b/Source/Processors/Editors/EventNodeEditor.cpp
index 36173b5e580869cb128511e388adfd21f23f7e84..26baa7c8215999c91bde3b6ddb076a8c3edcfb65 100644
--- a/Source/Processors/Editors/EventNodeEditor.cpp
+++ b/Source/Processors/Editors/EventNodeEditor.cpp
@@ -37,7 +37,7 @@ EventNodeEditor::EventNodeEditor (GenericProcessor* parentNode)
 	hzValues.add("1");
 	hzValues.add("2");
 
-	createRadioButtons(35, 65, 160, hzValues, "Event frequency");
+	//createRadioButtons(35, 65, 160, hzValues, "Event frequency");
 
 	// for (int n = 0; n < getNumChildComponents(); n++)
 	// {
diff --git a/Source/Processors/Editors/FilterEditor.cpp b/Source/Processors/Editors/FilterEditor.cpp
index 449d53126369705554d1c3830ac26358c907ea1e..a6c64763ccce0a9cec0af690b96a9a51f95fe382 100644
--- a/Source/Processors/Editors/FilterEditor.cpp
+++ b/Source/Processors/Editors/FilterEditor.cpp
@@ -44,8 +44,8 @@ FilterEditor::FilterEditor (GenericProcessor* parentNode)
 	highCutValues.add("6K");
 	highCutValues.add("9K");
 
-	createRadioButtons(35, 50, 160, lowCutValues, "Low Cutoff");
-	createRadioButtons(35, 90, 160, highCutValues, "High Cutoff");
+	//createRadioButtons(35, 50, 160, lowCutValues, "Low Cutoff");
+	//createRadioButtons(35, 90, 160, highCutValues, "High Cutoff");
 
 	// for (int n = 0; n < getNumChildComponents(); n++)
 	// {
diff --git a/Source/Processors/Editors/GenericEditor.cpp b/Source/Processors/Editors/GenericEditor.cpp
index b7fa8578f38aaafa4fe674ff48e3c5115483e8c1..4337516ecfcce3c2b7851e04a1f32483e4cbde11 100644
--- a/Source/Processors/Editors/GenericEditor.cpp
+++ b/Source/Processors/Editors/GenericEditor.cpp
@@ -24,6 +24,7 @@
 #include "GenericEditor.h"
 
 #include "ParameterEditor.h"
+#include "ChannelSelector.h"
 #include "../ProcessorGraph.h"
 #include "../RecordNode.h"
 #include "../../UI/ProcessorList.h"
@@ -32,12 +33,11 @@
 
 #include <math.h>
 
-GenericEditor::GenericEditor (GenericProcessor* owner)//, FilterViewport* vp) 
+GenericEditor::GenericEditor (GenericProcessor* owner) 
 	: AudioProcessorEditor (owner), isSelected(false),
-	  desiredWidth(150), tNum(-1), isEnabled(true), radioGroupId(1),
-	  accumulator(0.0), isFading(false), drawerButton(0), audioButton(0),
-	  recordButton(0), paramsButton(0), allButton(0), noneButton(0),
-	  numChannels(-1)
+	  desiredWidth(150), tNum(-1), isEnabled(true),
+	  accumulator(0.0), isFading(false), drawerButton(0),
+	  channelSelector(0)
 
 {
 	name = getAudioProcessor()->getName();
@@ -56,52 +56,30 @@ GenericEditor::GenericEditor (GenericProcessor* owner)//, FilterViewport* vp)
 
     	if (!owner->isSink())
     	{
-    		audioButton = new EditorButton("A", titleFont);
-    		audioButton->addListener(this);
-    		addChildComponent(audioButton);
-    		audioButton->setVisible(false);
-
-    		recordButton = new EditorButton("R", titleFont);
-    		recordButton->addListener(this);
-    		addChildComponent(recordButton);
-    		recordButton->setVisible(false);
-
-    		paramsButton = new EditorButton("P", titleFont);
-    		paramsButton->addListener(this);
-    		paramsButton->setVisible(false);
-    		addChildComponent(paramsButton);
-    		
-    		paramsButton->setToggleState(true, true);
+    		channelSelector = new ChannelSelector(true, titleFont);
+    	} else {
+    		channelSelector = new ChannelSelector(false, titleFont);
     	}
 
-	}
+    	addChildComponent(channelSelector);
+    	channelSelector->setVisible(false);
 
-	paramsChannels.clear();
-	audioChannels.clear();
-	recordChannels.clear();
+	}
 
 	backgroundGradient = ColourGradient(Colour(190, 190, 190), 0.0f, 0.0f, 
 										 Colour(185, 185, 185), 0.0f, 120.0f, false);
-
-	//backgroundGradient.addColour(0.05f, Colour(255, 255, 255));
 	backgroundGradient.addColour(0.2f, Colour(155, 155, 155));
-	//grad.addColour(0.5, Colours::lightgrey);
-	//grad.addColour(1.0f, Colours::grey);
 
 	addParameterEditors();
 
 	backgroundColor = Colour(10,10,10);
 
-	//refreshColors();
-
 	fadeIn();
 }
 
 GenericEditor::~GenericEditor()
 {
-	//std::cout << "  Generic editor for " << getName() << " being deleted with " << getNumChildComponents() << " children. " << std::endl;
 	deleteAllChildren();
-	//delete titleFont;
 }
 
 void GenericEditor::addParameterEditors()
@@ -110,6 +88,8 @@ void GenericEditor::addParameterEditors()
 	int maxX = 15;
 	int maxY = 30;
 
+	std::cout << "Adding parameter editors." << std::endl;
+
 	for (int i = 0; i < getProcessor()->getNumParameters(); i++)
 	{
 		ParameterEditor* p = new ParameterEditor(getProcessor()->getParameterReference(i), titleFont);												
@@ -121,7 +101,7 @@ void GenericEditor::addParameterEditors()
 		addAndMakeVisible(p);
 
 		maxY += dHeight;
-		maxY += 5;
+		maxY += 10;
 	}
 }
 
@@ -154,15 +134,8 @@ void GenericEditor::resized()
 	if (drawerButton != 0)
 		drawerButton->setBounds(getWidth()-14, 40, 10, getHeight()-60);
 	
-	if (audioButton != 0)
-		audioButton->setBounds(getWidth()-60, 4, 15, 15);
-	
-	if (recordButton != 0)
-		recordButton->setBounds(getWidth()-40, 4, 15, 15);
-	
-	if (paramsButton != 0)
-		paramsButton->setBounds(getWidth()-20, 4, 15, 15);
-
+	if (channelSelector != 0)
+	 	channelSelector->setBounds(desiredWidth - drawerWidth, 30, channelSelector->getDesiredWidth(), getHeight()-45);
 }
 
 
@@ -259,9 +232,6 @@ void GenericEditor::paint (Graphics& g)
 	g.fillRect(1,1,getWidth()-(2+offset),getHeight()-2);
 
 	// draw gray workspace
-	//g.setColour(Colour(140, 140, 140));
-	
-
 	g.setGradientFill(backgroundGradient);
 	g.fillRect(1,22,getWidth()-2, getHeight()-29);
 
@@ -313,14 +283,32 @@ void GenericEditor::timerCallback()
 
 void GenericEditor::buttonClicked(Button* button)
 {
+
+	std::cout << "Button clicked." << std::endl;
+
+	checkParameterButtons(button);
 	
 	checkDrawerButton(button);
-	checkChannelSelectors(button);
 
 	buttonEvent(button); // needed to inform subclasses of 
 						 // button event
 }
 
+void GenericEditor::sliderValueChanged(Slider* slider)
+{
+	std::cout << "Slider name: " << slider->getName() << std::endl;
+	std::cout << "Slider value: " << slider->getValue() << std::endl;
+
+	sliderEvent(slider);
+
+}
+
+bool GenericEditor::checkParameterButtons(Button* button)
+{
+	std::cout << "Button name: " << button->getName() << std::endl;
+	std::cout << "Button value: " << button->getButtonText() << std::endl;
+}
+
 bool GenericEditor::checkDrawerButton(Button* button)
 {
 	if (button == drawerButton)
@@ -328,29 +316,15 @@ bool GenericEditor::checkDrawerButton(Button* button)
 		if (drawerButton->getToggleState()) 
 		{
 			
+			channelSelector->setVisible(true);
 
-			if (recordButton != 0)
-				recordButton->setVisible(true);
-			if (audioButton != 0)
-				audioButton->setVisible(true);
-			if (paramsButton != 0)
-				paramsButton->setVisible(true);
-
-			drawerWidth = createChannelSelectors();
+			drawerWidth = channelSelector->getDesiredWidth() + 20;
 
 			desiredWidth += drawerWidth;
 
 		} else {
 			
-
-			if (recordButton != 0)
-				recordButton->setVisible(false);
-			if (audioButton != 0)
-				audioButton->setVisible(false);
-			if (paramsButton != 0)
-				paramsButton->setVisible(false);
-
-			removeChannelSelectors();
+			channelSelector->setVisible(false);
 
 			desiredWidth -= drawerWidth;
 		}
@@ -364,132 +338,6 @@ bool GenericEditor::checkDrawerButton(Button* button)
 
 }
 
-bool GenericEditor::checkChannelSelectors(Button* button)
-{
-
-
-
-	for (int n = 0; n < channelSelectorButtons.size(); n++)
-	{
-		if (button == channelSelectorButtons[n])
-		{
-
-		//	String type;
-
-			if (audioButton->getToggleState())
-			{
-				audioChannels.set(n,button->getToggleState());
-				//type = "Audio ";
-			}
-			else if (recordButton->getToggleState())
-			{
-				recordChannels.set(n,button->getToggleState());
-				int id = getProcessor()->getNodeId();
-
-				RecordNode* rn = getProcessorGraph()->getRecordNode();
-
-				std::cout << "Button " << n << " was pressed." << std::endl;
-				rn->setChannel(id, n);
-
-				if (button->getToggleState())
-					rn->setParameter(2, 1.0f);
-				else
-					rn->setParameter(2, 0.0f);
-			}		
-			else if (paramsButton->getToggleState())
-			{
-				paramsChannels.set(n,button->getToggleState());
-				//type = "Params ";	
-			}
-			
-			//std::cout << type << "button " << n << " clicked." << std::endl;
-			return true;
-			
-		}
-	}
-
-	Array<bool> arr;
-
-	if (button == audioButton)
-		{arr = audioChannels; allButton->setVisible(false);}// std::cout << "AUDIO" << std::endl;}
-	else if (button == paramsButton)
-		{arr = paramsChannels; if (allButton != 0) {allButton->setVisible(true);}}// std::cout << "PARAMS" << std::endl;}
-	else if (button == recordButton)
-		{arr = recordChannels; allButton->setVisible(true);}// std::cout << "RECORD" << std::endl;}
-
-	if (arr.size() > 0)
-	{
-		for (int n = 0; n < channelSelectorButtons.size(); n++)
-		{
-			channelSelectorButtons[n]->setToggleState(arr[n],false);
-		}
-
-		allButton->setToggleState(false,false);
-
-		return true;
-	}
-
-	if (button == noneButton)
-	{
-		for (int n = 0; n < channelSelectorButtons.size(); n++) 
-		{
-
-			channelSelectorButtons[n]->setToggleState(false,false);
-
-			if (audioButton->getToggleState())
-				audioChannels.set(n,false);
-			else if (recordButton->getToggleState())
-				recordChannels.set(n,false);			
-			else if (paramsButton->getToggleState())
-				paramsChannels.set(n,false);	
-
-		}
-
-		//allButton->setToggleState(false,false);
-
-		return true;
-	}
-
-	if (button == allButton)
-	{
-
-		for (int n = 0; n < channelSelectorButtons.size(); n++) 
-		{
-
-			channelSelectorButtons[n]->setToggleState(true,false);
-
-			if (audioButton->getToggleState())
-				audioChannels.set(n,true);
-			else if (recordButton->getToggleState())
-				recordChannels.set(n,true);			
-			else if (paramsButton->getToggleState())
-				paramsChannels.set(n,true);	
-
-		}
-
-		return true;
-	}
-
-	return false;
-
-}
-
-void GenericEditor::selectChannels(Array<int> arr)
-{
-	for (int i = 0; i < channelSelectorButtons.size(); i++)
-	{
-		channelSelectorButtons[i]->setToggleState(false, false);
-	}
-
-	for (int i = 0; i < arr.size(); i++)
-	{
-		if (i > -1 && i < channelSelectorButtons.size())
-		{
-			channelSelectorButtons[i]->setToggleState(true,false);
-		}
-	}
-
-}
 
 void GenericEditor::update()
 {
@@ -500,24 +348,16 @@ void GenericEditor::update()
 
 	std::cout << p->getName() << " updating settings." << std::endl;
 
-	if (!p->isSink())
-	{
-
-		if (p->getNumOutputs() != numChannels)
-		{
-			destroyChannelSelectors();
-		}
-
-		numChannels = p->getNumOutputs();
+	int numChannels;
 
-	} else {
-
-		if (p->getNumInputs() != numChannels)
-		{
-			destroyChannelSelectors();
-		}
+	if (channelSelector != 0)
+	{
+		if (!p->isSink())
+			numChannels = p->getNumOutputs();
+		else
+			numChannels = p->getNumInputs();
 
-		numChannels = p->getNumInputs();
+		channelSelector->setNumChannels(numChannels);
 	}
 
 	if (numChannels == 0)
@@ -536,207 +376,17 @@ void GenericEditor::update()
 
 Array<int> GenericEditor::getActiveChannels()
 {
-	Array<int> chans;
-
-	for (int n = 0; n < paramsChannels.size(); n++)
-	{
-		if (paramsChannels[n])
-		{
-			chans.add(n);
-		}
-
-	}
-
-	return chans;
-}
-
-void GenericEditor::createRadioButtons(int x, int y, int w, StringArray values, const String& groupName)
-{
-	int numButtons = values.size();
-	int width = w / numButtons;
-
-	for (int i = 0; i < numButtons; i++)
-	{
-
-		RadioButton* b = new RadioButton(values[i], radioGroupId, titleFont);
-		addAndMakeVisible(b);
-		b->setBounds(x+width*i,y,width,15);
-		b->addListener(this);
-		
-
-		// if (i == numButtons-1)
-		// {
-		// 	b->setToggleState(true, true);
-		// }
-	}
-
-	Label* l = new Label("Label",groupName);
-	addAndMakeVisible(l);
-	l->setBounds(x,y-15,200,10);
-	titleFont.setHeight(10);
-	l->setFont(titleFont);
-
-	radioGroupId++;
-}
-
-
-int GenericEditor::createChannelSelectors()
-{
-
-	GenericProcessor* p = getProcessor();
-
-	if (channelSelectorButtons.size() == 0) {
-
-		int width = 20;
-		int height = 14;
-		int numChannels;
-
-		if (!p->isSink())
-			numChannels = p->getNumOutputs();
-		else
-			numChannels = p->getNumInputs();
-
-		int nColumns = jmax((int) ceil(numChannels/4),1);
-		//std::cout << numChannels << " channels" << std::endl;
-		//std::cout << nColumns << " columns" << std::endl;
-
-		for (int n = 1; n < numChannels+1; n++)
-		{
-			String channelName = "";
-			channelName += n;
-			ChannelSelectorButton* b = new ChannelSelectorButton(channelName, titleFont);
-			channelSelectorButtons.add(b);
-			addAndMakeVisible(b);
-			b->addListener(this);
-			b->setBounds(desiredWidth+width*((n-1)%nColumns)-12,
-			  floor((n-1)/nColumns)*height+40, width-1, height-1);
-			  
-			audioChannels.add(false);
-			recordChannels.add(false);
-			paramsChannels.add(false);
-
-		}
-
-		if (allButton == 0)
-		{
-			allButton = new ChannelSelectorButton("+",titleFont);
-			addAndMakeVisible(allButton);
-			allButton->addListener(this);
-			allButton->setVisible(true);
-			allButton->setClickingTogglesState(false);
-			allButton->setBounds(desiredWidth-30,
-				  40, height, height);
-		}
-
-		if (noneButton == 0)
-		{
-			noneButton = new ChannelSelectorButton("-",titleFont);
-			addAndMakeVisible(noneButton);
-			noneButton->addListener(this);
-			noneButton->setVisible(true);
-			noneButton->setClickingTogglesState(false);
-			noneButton->setBounds(desiredWidth-30,
-				  60, height, height);
-		}
-
-		 return nColumns*width+ 15;
-
-	} else {
-
-		for (int n = 0; n < channelSelectorButtons.size(); n++)
-		{
-			channelSelectorButtons[n]->setVisible(true);
-
-			if (!p->isSink()) {
-
-				if (audioButton->getToggleState())
-					channelSelectorButtons[n]->setToggleState(audioChannels[n],false);
-				else if (recordButton->getToggleState())
-					channelSelectorButtons[n]->setToggleState(recordChannels[n],false);
-				else if (paramsButton->getToggleState())
-					channelSelectorButtons[n]->setToggleState(paramsChannels[n],false);
-				
-			}
-
-		}
-
-		allButton->setVisible(true);
-		noneButton->setVisible(true);
-
-		return drawerWidth;
-	}
-
-}
-
-void GenericEditor::removeChannelSelectors()
-{
-	for (int n = 0; n < channelSelectorButtons.size(); n++)
-	{
-		channelSelectorButtons[n]->setVisible(false);
-	}
-
-	allButton->setVisible(false);
-	noneButton->setVisible(false);
-
-}
-
-void GenericEditor::destroyChannelSelectors()
-{
-	for (int n = 0; n < channelSelectorButtons.size(); n++)
-	{
-		removeChildComponent(channelSelectorButtons[n]);
-		ChannelSelectorButton* t = channelSelectorButtons.remove(n);
-     	deleteAndZero(t);
-	}
-
-	if (allButton != 0)
-		allButton->setVisible(false);
-	
-	if (allButton != 0)
-		noneButton->setVisible(false);
-
-	recordChannels.clear();
-	audioChannels.clear();
-	paramsChannels.clear();
-	channelSelectorButtons.clear();
+	Array<int> a;// = channelSelector->getActiveChannels();
+	return a;
 }
 
-RadioButton::RadioButton(const String& name, int groupId, Font f) : Button(name) 
+bool GenericEditor::getRecordStatus(int chan)
 {
-
-    setRadioGroupId(groupId);
-    setClickingTogglesState(true);
-
-    buttonFont = f;
-    buttonFont.setHeight(10);
-
-    // MemoryInputStream mis(BinaryData::silkscreenserialized, BinaryData::silkscreenserializedSize, false);
-    // Typeface::Ptr typeface = new CustomTypeface(mis);
-    // buttonFont = Font(typeface);
-    // 
+	return channelSelector->getRecordStatus(chan);
 }
 
 
-void RadioButton::paintButton(Graphics &g, bool isMouseOver, bool isButtonDown)
-{
-    if (getToggleState() == true)
-        g.setColour(Colours::orange);
-    else 
-        g.setColour(Colours::darkgrey);
-
-    if (isMouseOver)
-        g.setColour(Colours::white);
-
-    g.fillRect(0,0,getWidth(),getHeight());
-
-    g.setFont(buttonFont);
-    g.setColour(Colours::black);
-
-    g.drawRect(0,0,getWidth(),getHeight(),1.0);
-
-    g.drawText(getName(),0,0,getWidth(),getHeight(),Justification::centred,true);
-}
-
+/////////////////////// BUTTONS ///////////////////////////////
 
 DrawerButton::DrawerButton(const String& name) : Button(name)
 {
@@ -746,7 +396,7 @@ DrawerButton::DrawerButton(const String& name) : Button(name)
 void DrawerButton::paintButton(Graphics& g, bool isMouseOver, bool isButtonDown)
 {
 	if (isMouseOver)
-		g.setColour(Colours::white);
+		g.setColour(Colours::yellow);
 	else
 		g.setColour(Colours::darkgrey);
 	
@@ -756,56 +406,11 @@ void DrawerButton::paintButton(Graphics& g, bool isMouseOver, bool isButtonDown)
 
 }
 
-
-EditorButton::EditorButton(const String& name, Font f) : Button(name) 
-{
-
-	buttonFont = f;
-	buttonFont.setHeight(10);
-
-    setRadioGroupId(999);
-    setClickingTogglesState(true);
-
-}
-
-
-void EditorButton::paintButton(Graphics &g, bool isMouseOver, bool isButtonDown)
-{
-    if (getToggleState() == true)
-        g.setColour(Colours::orange);
-    else 
-        g.setColour(Colours::darkgrey);
-
-    if (isMouseOver)
-        g.setColour(Colours::white);
-
-    int b = 2;
-
-    g.fillEllipse(b,b,getWidth()-2*b,getHeight()-2*b);
-
-    g.setFont(buttonFont);
-    g.setColour(Colours::black);
-
-    g.drawEllipse(b,b,getWidth()-2*b,getHeight()-2*b,1.0);
-
-    g.drawText(getName(),0,0,getWidth(),getHeight(),Justification::centred,true);
-}
-
-
-ChannelSelectorButton::ChannelSelectorButton(const String& name, Font f) : Button(name) 
-{
-    setClickingTogglesState(true);
-
-    buttonFont = f;
-    buttonFont.setHeight(10);
-}
-
-
-void ChannelSelectorButton::paintButton(Graphics &g, bool isMouseOver, bool isButtonDown)
+void UtilityButton::paintButton(Graphics& g, bool isMouseOver, bool isButtonDown)
 {
-    if (getToggleState() == true)
+ 	if (getToggleState() == true)
         g.setColour(Colours::orange);
-    else 
+    else
         g.setColour(Colours::darkgrey);
 
     if (isMouseOver)
@@ -813,46 +418,29 @@ void ChannelSelectorButton::paintButton(Graphics &g, bool isMouseOver, bool isBu
 
     g.fillRect(0,0,getWidth(),getHeight());
 
-    g.setFont(buttonFont);
+    g.setFont(font);
     g.setColour(Colours::black);
 
     g.drawRect(0,0,getWidth(),getHeight(),1.0);
 
     g.drawText(getName(),0,0,getWidth(),getHeight(),Justification::centred,true);
-}
-
-//// BUTTONS ////
-
-void PlusButton::paintButton(Graphics& g, bool isMouseOver, bool isButtonDown)
-{
-    g.fillAll(Colours::orange);
-    g.setColour(Colours::black);
-    g.drawRect(0,0,getWidth(),getHeight(),1.0);
-
-    if (isMouseOver)
-    {
-        g.setColour(Colours::white);
-    } else {
-        g.setColour(Colours::black);
-    }
-
     // if (isButtonDown)
     // {
     //     g.setColour(Colours::white);
     // }
 
-    int thickness = 1;
-    int offset = 3;
+    // int thickness = 1;
+    // int offset = 3;
 
-    g.fillRect(getWidth()/2-thickness,
-               offset, 
-               thickness*2,
-               getHeight()-offset*2);
+    // g.fillRect(getWidth()/2-thickness,
+    //            offset, 
+    //            thickness*2,
+    //            getHeight()-offset*2);
 
-    g.fillRect(offset,
-               getHeight()/2-thickness,
-               getWidth()-offset*2,
-               thickness*2);
+    // g.fillRect(offset,
+    //            getHeight()/2-thickness,
+    //            getWidth()-offset*2,
+    //            thickness*2);
 }
    
 
diff --git a/Source/Processors/Editors/GenericEditor.h b/Source/Processors/Editors/GenericEditor.h
index 8e0a3123f40312dd2ed2a8560b5b8af53760e333..a1f66899303038dd90a60b6c647ca83668598f18 100644
--- a/Source/Processors/Editors/GenericEditor.h
+++ b/Source/Processors/Editors/GenericEditor.h
@@ -44,11 +44,10 @@
 
 class GenericProcessor;
 class DrawerButton;
-class EditorButton;
-class ChannelSelectorButton;
 class TriangleButton;
-class PlusButton;
+class UtilityButton;
 class ParameterEditor;
+class ChannelSelector;
 
 class GenericEditor : public AudioProcessorEditor,
                       public Timer,
@@ -87,12 +86,8 @@ public:
 	virtual void switchSource() { }; // needed for MergerEditor
 
 	GenericProcessor* getProcessor() const {return (GenericProcessor*) getAudioProcessor();}
-	
-	void createRadioButtons(int x, int y, int w, StringArray values, const String& name);
-		
-	void fadeIn();
 
-	int radioGroupId;
+	void fadeIn();
 
 	bool isFading;
 
@@ -100,10 +95,13 @@ public:
 
 	virtual void buttonClicked(Button* button);
 	virtual void buttonEvent(Button* button) {}
-	virtual void sliderValueChanged(Slider* slider) {}
+	virtual void sliderValueChanged(Slider* slider);
+	virtual void sliderEvent(Slider* slider) {}
 
 	bool checkDrawerButton(Button* button);
-	bool checkChannelSelectors(Button* button);
+	bool checkParameterButtons(Button* button);
+
+	bool getRecordStatus(int chan);
 
 	void selectChannels(Array<int>);
 
@@ -114,27 +112,22 @@ public:
 
 	Array<int> getActiveChannels();
 
-	Array<bool> audioChannels;
-	Array<bool> recordChannels;
-	Array<bool> paramsChannels;
-
+	Font titleFont;
 
 protected:
 	DrawerButton* drawerButton;
 	int drawerWidth;
 
 	virtual void addParameterEditors();
-	
+
+	ChannelSelector* channelSelector;
+
 private:
 
 	virtual void timerCallback();
 
 	virtual void resized();
 
-	virtual int createChannelSelectors();
-	virtual void removeChannelSelectors();
-	virtual void destroyChannelSelectors();
-
 	Colour backgroundColor;
 	ColourGradient backgroundGradient;
 
@@ -143,49 +136,13 @@ private:
 
 	int tNum;
 
-	int numChannels;
-
-
-
-	EditorButton* audioButton;
-	EditorButton* recordButton;
-	EditorButton* paramsButton;
-
-	
-
-	Array<ChannelSelectorButton*> channelSelectorButtons;
-
-	ChannelSelectorButton* allButton;
-	ChannelSelectorButton* noneButton;
-
-
 	String name;
 
-protected:
-
-	Font titleFont;
-
-
 	JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (GenericEditor);
 
 };
 
 
-
-
-class RadioButton : public Button
-{
-public:
-    RadioButton(const String& name, int groupId, Font f);// : Button("Name") {configurationChanged = true;}
-    ~RadioButton() {}
-
-private:
-
-    void paintButton(Graphics &g, bool isMouseOver, bool isButtonDown);
-
-    Font buttonFont;
-};
-
 class DrawerButton : public Button
 {
 public:
@@ -196,29 +153,6 @@ private:
 		
 };
 
-class EditorButton : public Button
-{
-public:
-	EditorButton(const String& name, Font f);
-	~EditorButton() {}
-private:
-	void paintButton(Graphics& g, bool isMouseOver, bool isButtonDown);
-	
-	int type;
-	Font buttonFont;
-};
-
-class ChannelSelectorButton : public Button
-{
-public:
-	ChannelSelectorButton(const String& name, Font f);
-	~ChannelSelectorButton() {}
-private:
-	void paintButton(Graphics& g, bool isMouseOver, bool isButtonDown);
-	
-	int type;
-	Font buttonFont;
-};
 
 class TriangleButton : public Button
 {
@@ -232,14 +166,18 @@ private:
     int direction;
 };
 
-class PlusButton : public Button
+class UtilityButton : public Button
 {
 public:
-    PlusButton() : Button("Plus") {}
-    ~PlusButton() {}
+    UtilityButton(const String& label_, Font font_) :
+    	 Button("Utility"), label(label_), font(font_) {}
+    ~UtilityButton() {}
 private:
     void paintButton(Graphics& g, bool isMouseOver, bool isButtonDown);
 
+    const String label;
+    Font font;
+
 };
 
 
diff --git a/Source/Processors/Editors/LfpDisplayEditor.cpp b/Source/Processors/Editors/LfpDisplayEditor.cpp
index da81819d1782a1134616553ba3a176034ed9c2b4..7ef2a4a0557c46014dc5a9621f09f115d971128a 100644
--- a/Source/Processors/Editors/LfpDisplayEditor.cpp
+++ b/Source/Processors/Editors/LfpDisplayEditor.cpp
@@ -39,7 +39,7 @@ LfpDisplayEditor::LfpDisplayEditor (GenericProcessor* parentNode)
 	timeBaseValues.add("5");
 	timeBaseValues.add("10");
 
-	createRadioButtons(35, 50, 160, timeBaseValues, "Display width (s)");
+	//createRadioButtons(35, 50, 160, timeBaseValues, "Display width (s)");
 
 	StringArray displayGainValues;
 	displayGainValues.add("1");
@@ -47,7 +47,7 @@ LfpDisplayEditor::LfpDisplayEditor (GenericProcessor* parentNode)
 	displayGainValues.add("4");
 	displayGainValues.add("8");
 
-	createRadioButtons(35, 90, 160, displayGainValues, "Display Gain");
+	//createRadioButtons(35, 90, 160, displayGainValues, "Display Gain");
 
 
 }
diff --git a/Source/Processors/Editors/ParameterEditor.cpp b/Source/Processors/Editors/ParameterEditor.cpp
index 541ab3d36bfdbf3e0a0df29acf319358c97e5074..db6a162e1aaf869a840da091c8f89388144fa268 100644
--- a/Source/Processors/Editors/ParameterEditor.cpp
+++ b/Source/Processors/Editors/ParameterEditor.cpp
@@ -34,6 +34,8 @@ ParameterEditor::ParameterEditor(Parameter& p, Font labelFont)
 		ParameterCheckbox* pc = new ParameterCheckbox((bool) p.getDefaultValue());
 		addAndMakeVisible(pc);
 		pc->setBounds(0,0,12, 12);
+		pc->setName(p.getName());
+		buttonArray.add(pc);
 
 		Label* label = new Label(p.getName(), p.getName());
 		labelFont.setHeight(10);
@@ -56,7 +58,9 @@ ParameterEditor::ParameterEditor(Parameter& p, Font labelFont)
 												  labelFont);
 
 		ps->setBounds(0,0, 40, 40);
+		ps->setName(p.getName());
 		addAndMakeVisible(ps);
+		sliderArray.add(ps);
 
 		Label* label = new Label(p.getName(), p.getName());
 		labelFont.setHeight(10);
@@ -99,11 +103,12 @@ ParameterEditor::ParameterEditor(Parameter& p, Font labelFont)
 
 			ParameterButton* pb = new ParameterButton(possibleValues[i], buttonType, labelFont);
 			pb->setBounds(buttonWidth*i, 12, buttonWidth, 18);
+			pb->setName(p.getName());
+			buttonArray.add(pb);
 
 			if (i == (int) p.getDefaultValue())
 				pb->setToggleState(true, false);
 
-			componentArray.add(pb);
 			addAndMakeVisible(pb);
 
 		}
@@ -118,6 +123,26 @@ ParameterEditor::~ParameterEditor()
 	deleteAllChildren();
 }
 
+void ParameterEditor::parentHierarchyChanged()
+{
+	std::cout << "Parent hierarchy changed." << std::endl;
+
+	// register all children with parent --> not currently working
+	if (getParentComponent() != 0) {
+
+		for (int i = 0; i < sliderArray.size(); i++)
+		{
+			sliderArray[i]->addListener((Slider::Listener*) getParentComponent());
+		}
+
+		for (int i = 0; i < buttonArray.size(); i++)
+		{
+			buttonArray[i]->addListener((Button::Listener*) getParentComponent());
+		}
+	}
+
+}
+
 
 /// ============= PARAMETER BUTTON ==================
 
@@ -126,6 +151,7 @@ ParameterButton::ParameterButton(var value, int buttonType, Font labelFont) :
 	font(labelFont)
 {
 
+	setButtonText(valueString);
 	setRadioGroupId(1999);
 	setClickingTogglesState(true);
 
@@ -176,8 +202,6 @@ void ParameterButton::paintButton(Graphics& g, bool isMouseOver, bool isButtonDo
 	g.setColour(Colours::darkgrey);
 	g.drawSingleLineText(valueString, getWidth()/2 - stringWidth/2, 12);
 
-
- 
 };
 
 void ParameterButton::resized()
diff --git a/Source/Processors/Editors/ParameterEditor.h b/Source/Processors/Editors/ParameterEditor.h
index 729d3a80410276a6936f6dd17290615a390a8897..c3d592acd668397b619a3ea2e39216ad09ee83d5 100644
--- a/Source/Processors/Editors/ParameterEditor.h
+++ b/Source/Processors/Editors/ParameterEditor.h
@@ -21,14 +21,14 @@
 
 */
 
+#ifndef __PARAMETEREDITOR_H_44537DA9__
+#define __PARAMETEREDITOR_H_44537DA9__
+
 #include "../../../JuceLibraryCode/JuceHeader.h"
 #include "GenericEditor.h"
 #include "../Parameter.h"
 #include <stdio.h>
 
-#ifndef __PARAMETEREDITOR_H_44537DA9__
-#define __PARAMETEREDITOR_H_44537DA9__
-
 /**
   
   Automatically creates an interactive editor for a particular
@@ -45,13 +45,16 @@ public:
 	ParameterEditor(Parameter& p, Font labelFont);
 	~ParameterEditor();
 
-	
+
     int desiredWidth;
     int desiredHeight;
 
+    void parentHierarchyChanged();
+
 private:
 
-	Array<Component*> componentArray;
+	Array<Slider*> sliderArray;
+	Array<Button*> buttonArray;
 
 	enum {
 		LEFT,
@@ -87,8 +90,6 @@ private:
     ColourGradient neutralGrad;
     ColourGradient neutralOverGrad;
 
-
-
     enum {
 		LEFT,
 		MIDDLE,
diff --git a/Source/Processors/Editors/SignalGeneratorEditor.cpp b/Source/Processors/Editors/SignalGeneratorEditor.cpp
index 57124b20d08821b612cb80ad143cc7423aa74e40..04bdf09f309a6fa43d64bba379fb1da726632f52 100644
--- a/Source/Processors/Editors/SignalGeneratorEditor.cpp
+++ b/Source/Processors/Editors/SignalGeneratorEditor.cpp
@@ -32,7 +32,7 @@ SignalGeneratorEditor::SignalGeneratorEditor (GenericProcessor* parentNode)
 	: GenericEditor(parentNode), amplitudeSlider(0), frequencySlider(0), phaseSlider(0)
 
 {
-	desiredWidth = 270;
+	desiredWidth = 250;
 
 	int buttonWidth = 31;
 	int buttonHeight = 19;
@@ -93,30 +93,30 @@ SignalGeneratorEditor::~SignalGeneratorEditor()
 	deleteAllChildren();
 }
 
-void SignalGeneratorEditor::sliderValueChanged (Slider* slider)
-{
+// void SignalGeneratorEditor::sliderValueChanged (Slider* slider)
+// {
 
-	Array<int> chans = getActiveChannels();
+// 	// Array<int> chans = getActiveChannels();
 	
-	//std::cout << chans.size() << " channels selected." << std::endl;
+// 	// //std::cout << chans.size() << " channels selected." << std::endl;
 
-	GenericProcessor* p = (GenericProcessor*) getAudioProcessor();
+// 	// GenericProcessor* p = (GenericProcessor*) getAudioProcessor();
 
-	for (int n = 0; n < chans.size(); n++) {
+// 	// for (int n = 0; n < chans.size(); n++) {
 		
-		p->setCurrentChannel(chans[n]);
+// 	// 	p->setCurrentChannel(chans[n]);
 
-		if (slider == amplitudeSlider)
-			p->setParameter(0,slider->getValue());
-		else if (slider == frequencySlider)
-			p->setParameter(1,slider->getValue());
-		else if (slider == phaseSlider)
-			p->setParameter(2,slider->getValue());
+// 	// 	if (slider == amplitudeSlider)
+// 	// 		p->setParameter(0,slider->getValue());
+// 	// 	else if (slider == frequencySlider)
+// 	// 		p->setParameter(1,slider->getValue());
+// 	// 	else if (slider == phaseSlider)
+// 	// 		p->setParameter(2,slider->getValue());
 
-	}
+// 	// }
 
 
-}
+// }
 
 void SignalGeneratorEditor::buttonEvent (Button* button)
 {
diff --git a/Source/Processors/Editors/SignalGeneratorEditor.h b/Source/Processors/Editors/SignalGeneratorEditor.h
index ffe55aa6cc87fd4dace829a8d53f8c2f78b498e6..cdd43fe0638df2d3ca5023c6f5735b92de773578 100644
--- a/Source/Processors/Editors/SignalGeneratorEditor.h
+++ b/Source/Processors/Editors/SignalGeneratorEditor.h
@@ -36,7 +36,7 @@ class SignalGeneratorEditor : public GenericEditor,
 public:
 	SignalGeneratorEditor (GenericProcessor* parentNode);
 	virtual ~SignalGeneratorEditor();
-	void sliderValueChanged (Slider* slider);
+	//void sliderValueChanged (Slider* slider);
     void buttonEvent(Button* button);
     void labelTextChanged(Label* label);
 
diff --git a/Source/Processors/Editors/SpikeDetectorEditor.cpp b/Source/Processors/Editors/SpikeDetectorEditor.cpp
index c3e480bea000a976a70f01d7dea63ded216ca36d..f61fafd376ddc3277b5f4af579fd4b026c05709e 100644
--- a/Source/Processors/Editors/SpikeDetectorEditor.cpp
+++ b/Source/Processors/Editors/SpikeDetectorEditor.cpp
@@ -78,7 +78,7 @@ SpikeDetectorEditor::SpikeDetectorEditor (GenericProcessor* parentNode)
     downButton->setBounds(50,50,10,8);
     addAndMakeVisible(downButton);
 
-    plusButton = new PlusButton();
+    plusButton = new UtilityButton("+", titleFont);
     plusButton->addListener(this);
     plusButton->setBounds(15,42,14,14);
     addAndMakeVisible(plusButton);
diff --git a/Source/Processors/Editors/SpikeDetectorEditor.h b/Source/Processors/Editors/SpikeDetectorEditor.h
index 0fc9544400ec4745a5c50fc5530670d17b1adea8..bf8d192c3b399848ab78948615b757f8f7a64a8c 100644
--- a/Source/Processors/Editors/SpikeDetectorEditor.h
+++ b/Source/Processors/Editors/SpikeDetectorEditor.h
@@ -29,7 +29,7 @@
 #include "GenericEditor.h"
 
 class TriangleButton;
-class PlusButton;
+class UtilityButton;
 
 class ElectrodeButton : public Button
 {
@@ -90,7 +90,7 @@ private:
     Label* numElectrodes;
     TriangleButton* upButton;
     TriangleButton* downButton;
-    PlusButton* plusButton;
+    UtilityButton* plusButton;
 
     OwnedArray<ElectrodeButton> electrodeButtons;
     Array<ElectrodeEditorButton*> electrodeEditorButtons;
diff --git a/Source/Processors/Editors/SpikeDisplayEditor.cpp b/Source/Processors/Editors/SpikeDisplayEditor.cpp
index f697ea3529a628480304ada750baae841ed23f53..b55ac351e2e8b0a6ea895e5469b1d74af2d77b41 100644
--- a/Source/Processors/Editors/SpikeDisplayEditor.cpp
+++ b/Source/Processors/Editors/SpikeDisplayEditor.cpp
@@ -49,33 +49,33 @@ void SpikeDisplayEditor::initializeButtons(){
 	y += h + yPad/2;
 
 	
-	panDownBtn = new ChannelSelectorButton("-", titleFont);
+	panDownBtn = new UtilityButton("-", titleFont);
 	panDownBtn->setBounds(x, y, w, h);
 	panDownBtn->setClickingTogglesState(false);
 	panDownBtn->addListener(this);
 	x+= w+xPad;
 
-	panUpBtn = new ChannelSelectorButton("+", titleFont);
+	panUpBtn = new UtilityButton("+", titleFont);
 	panUpBtn->setBounds(x, y, w, h); 
 	panUpBtn->setClickingTogglesState(false);
 	panUpBtn->addListener(this);
 	x+= w+xPad*2;
 
 	
-	zoomOutBtn = new ChannelSelectorButton("-", titleFont);
+	zoomOutBtn = new UtilityButton("-", titleFont);
 	zoomOutBtn->setBounds(x,y,w,h);
 	zoomOutBtn->setClickingTogglesState(false);
 	zoomOutBtn->addListener(this);
 	x += w + xPad;
 
-	zoomInBtn = new ChannelSelectorButton("+", titleFont);
+	zoomInBtn = new UtilityButton("+", titleFont);
 	zoomInBtn->setBounds(x,y,w,h);
 	zoomInBtn->setClickingTogglesState(false);
 	zoomInBtn->addListener(this);
 	x += w + xPad*3;
 
 
-	clearBtn = new ChannelSelectorButton("Clear", titleFont);
+	clearBtn = new UtilityButton("Clear", titleFont);
 	clearBtn->setBounds(x, y, w*2 + xPad, h);
 	clearBtn->setClickingTogglesState(false);
 	clearBtn->addListener(this);
@@ -87,7 +87,7 @@ void SpikeDisplayEditor::initializeButtons(){
 
 	//panLabel->setFont(titleFont);
 
-	saveImgBtn = new ChannelSelectorButton("Save", titleFont);
+	saveImgBtn = new UtilityButton("Save", titleFont);
 	saveImgBtn->setBounds(x,y,w*2 + xPad, h);
 	saveImgBtn->setClickingTogglesState(false);
 	saveImgBtn->addListener(this);
@@ -108,7 +108,7 @@ void SpikeDisplayEditor::initializeButtons(){
 	y += h + yPad/2;
 	//x += w/2;
 
-	allSubChansBtn = new ChannelSelectorButton("All", titleFont);
+	allSubChansBtn = new UtilityButton("All", titleFont);
 	allSubChansBtn->setBounds(x,y,w*2+xPad,h);
 	allSubChansBtn->addListener(this);
 	allSubChansBtn->setToggleState(true, false);
@@ -119,7 +119,7 @@ void SpikeDisplayEditor::initializeButtons(){
 		String s = "";
 		s += i;
 
-		subChanBtn[i] = new ChannelSelectorButton(s, titleFont);
+		subChanBtn[i] = new UtilityButton(s, titleFont);
 		subChanBtn[i]->setBounds(x,y,w,h);
 		subChanBtn[i]->addListener(this);
 		subChanBtn[i]->setToggleState(true, false);
@@ -203,7 +203,7 @@ void SpikeDisplayEditor::buttonCallback(Button* button)
 			if(button == subChanBtn[i])
 			{
 				std::cout<<"SubChannel:"<<i<< " set to:";
-				subChanSelected[i] = ((ChannelSelectorButton*) button)->getToggleState();
+				subChanSelected[i] = ((UtilityButton*) button)->getToggleState();
 				std::cout<< subChanSelected[i]<<std::endl;
 			}
 
diff --git a/Source/Processors/GenericProcessor.cpp b/Source/Processors/GenericProcessor.cpp
index 0e96ba6428468d2a683c04562d547404a71a07f3..8df1cb70c6515ca4575b3f7ad1702fe87e692480 100644
--- a/Source/Processors/GenericProcessor.cpp
+++ b/Source/Processors/GenericProcessor.cpp
@@ -333,7 +333,7 @@ void GenericProcessor::update()
 bool GenericProcessor::recordStatus(int chan)
 {
 
-	return getEditor()->recordChannels[chan];
+	return getEditor()->getRecordStatus(chan);//recordChannels[chan];
 
 
 }
diff --git a/Source/Processors/SignalGenerator.cpp b/Source/Processors/SignalGenerator.cpp
index e8e4a088f5cbfce43a983e05ebac1f49d569394b..43e59ced0f313dad30e3644fc736ccadc4b266dc 100644
--- a/Source/Processors/SignalGenerator.cpp
+++ b/Source/Processors/SignalGenerator.cpp
@@ -42,13 +42,14 @@ SignalGenerator::SignalGenerator()
 	a.add(2);
 	a.add(3);
 
-	//parameters.add(Parameter("SVN",0.0f, 100.0f, 50.0f));
 
 	parameters.add(Parameter("Param 1",a, 0));//true);//a,0);
 
-	parameters.add(Parameter("Param 1",a, 0));//true);//a,0);
+	parameters.add(Parameter("PARAM",0.0f, 100.0f, 50.0f));
+
+	//parameters.add(Parameter("Param 1",a, 0));//true);//a,0);
 
-	parameters.add(Parameter("Param 2",true));
+	//parameters.add(Parameter("Param 2",true));
 
 }
 
diff --git a/Source/UI/EditorViewport.cpp b/Source/UI/EditorViewport.cpp
index 0652adc754df3dc3651e1dc7222f0178d22dcbce..c0b4defc35f2844b2351fc6b76ba70802693d9c5 100644
--- a/Source/UI/EditorViewport.cpp
+++ b/Source/UI/EditorViewport.cpp
@@ -472,7 +472,9 @@ void EditorViewport::mouseDown(const MouseEvent &e) {
     for (int i = 0; i < editorArray.size(); i++) {
         
         if (e.eventComponent == editorArray[i]
-             || e.eventComponent->getParentComponent() == editorArray[i]) {
+             || e.eventComponent->getParentComponent() == editorArray[i] ||
+                e.eventComponent->getParentComponent()->getParentComponent() ==
+                        editorArray[i]) {
             editorArray[i]->select();
         } else {
             editorArray[i]->deselect();
diff --git a/open-ephys.jucer b/open-ephys.jucer
index bfaed967d86eccc72f1b5d2ca1010e8dd407522c..070efce95ffd907fa53e752d0048af7478fa003a 100644
--- a/open-ephys.jucer
+++ b/open-ephys.jucer
@@ -255,6 +255,10 @@
         <FILE id="hGnGAjh" name="EventNode.cpp" compile="1" resource="0" file="Source/Processors/EventNode.cpp"/>
         <FILE id="dUtRN6" name="EventNode.h" compile="0" resource="0" file="Source/Processors/EventNode.h"/>
         <GROUP id="AqvwO6w" name="Editors">
+          <FILE id="rZGNxjv" name="ChannelSelector.cpp" compile="1" resource="0"
+                file="Source/Processors/Editors/ChannelSelector.cpp"/>
+          <FILE id="Yga4B3Z" name="ChannelSelector.h" compile="0" resource="0"
+                file="Source/Processors/Editors/ChannelSelector.h"/>
           <FILE id="qWhyk9h" name="ParameterEditor.cpp" compile="1" resource="0"
                 file="Source/Processors/Editors/ParameterEditor.cpp"/>
           <FILE id="3PkZxza" name="ParameterEditor.h" compile="0" resource="0"