diff --git a/Builds/MacOSX/open-ephys.xcodeproj/project.xcworkspace/xcuserdata/Josh.xcuserdatad/UserInterfaceState.xcuserstate b/Builds/MacOSX/open-ephys.xcodeproj/project.xcworkspace/xcuserdata/Josh.xcuserdatad/UserInterfaceState.xcuserstate
index 08a70b2fb0568f9c81af25d62bf13e3c94572cf4..18f14965ee80b51b5296b80fbdd9024fafcdf97d 100755
Binary files a/Builds/MacOSX/open-ephys.xcodeproj/project.xcworkspace/xcuserdata/Josh.xcuserdatad/UserInterfaceState.xcuserstate and b/Builds/MacOSX/open-ephys.xcodeproj/project.xcworkspace/xcuserdata/Josh.xcuserdatad/UserInterfaceState.xcuserstate differ
diff --git a/Source/Processors/DataThreads/FileReaderThread.cpp b/Source/Processors/DataThreads/FileReaderThread.cpp
index 3b5b8c04b2767465a4f5ab0263a825466b6e7300..553725472d38c2656ecdedd1ce90d4e844726c16 100755
--- a/Source/Processors/DataThreads/FileReaderThread.cpp
+++ b/Source/Processors/DataThreads/FileReaderThread.cpp
@@ -137,7 +137,7 @@ bool FileReaderThread::updateBuffer()
 
         for (int n = 0; n < bufferSize; n++)
         {
-            thisSample[chan] = float(-readBuffer[n]);
+            thisSample[chan] = float(-readBuffer[n])*0.035;
 
             if (chan == 15)
             {
diff --git a/Source/Processors/Editors/GenericEditor.cpp b/Source/Processors/Editors/GenericEditor.cpp
index 9c77c1c990a08165ce114e48a2302ea5a60fc740..28f5f8bcf739e8cc683d5cad6f2313ad55e36983 100755
--- a/Source/Processors/Editors/GenericEditor.cpp
+++ b/Source/Processors/Editors/GenericEditor.cpp
@@ -769,22 +769,27 @@ void TriangleButton::paintButton(Graphics& g, bool isMouseOver, bool isButtonDow
 
 }
 
-void GenericEditor::updateParameterButtons(int parameterIndex=-1){
+void GenericEditor::updateParameterButtons(int parameterIndex)
+{
+
     if (parameterEditors.size()==0)
     {
         //Checks if there is a parameter editor, and stops a bug if there isn't.
         std::cout << "No parameterEditors" << std::endl;
     }
-    else{
-    if (parameterIndex==-1){
-        for (int i = 0; i < parameterEditors.size(); ++i)
+    else
+    {
+        if (parameterIndex == -1)
         {
-            parameterEditors[i]->channelSelectionUI();
+            for (int i = 0; i < parameterEditors.size(); ++i)
+            {
+                parameterEditors[i]->channelSelectionUI();
+            }
+        }
+        else
+        {
+            parameterEditors[parameterIndex]->channelSelectionUI();
         }
-    }
-    else{
-        parameterEditors[parameterIndex]->channelSelectionUI();
-    }
     std::cout << "updateParameterButtons" << std::endl;
     }
 }
diff --git a/Source/Processors/Editors/GenericEditor.h b/Source/Processors/Editors/GenericEditor.h
index 214bae945e2b40cca95609c757cc7d7ae7cde4c6..c8c59178b25dcf4e1c310ff5869d924bd6bdf9a1 100755
--- a/Source/Processors/Editors/GenericEditor.h
+++ b/Source/Processors/Editors/GenericEditor.h
@@ -238,7 +238,7 @@ public:
     virtual void loadEditorParameters(XmlElement* xml);
 
     /** Syncs parametereditor colors with parameter values */
-    void updateParameterButtons(int parameterIndex);
+    void updateParameterButtons(int parameterIndex = -1);
 protected:
 
     /** A pointer to the button that opens the drawer for the ChannelSelector. */
diff --git a/Source/Processors/Editors/LfpDisplayEditor.cpp b/Source/Processors/Editors/LfpDisplayEditor.cpp
index 42a6712a657359adb8fc308ad3f7cf15162ae11e..b5564dd525351bf80d48253334697989aa51128b 100755
--- a/Source/Processors/Editors/LfpDisplayEditor.cpp
+++ b/Source/Processors/Editors/LfpDisplayEditor.cpp
@@ -63,3 +63,4 @@ void LfpDisplayEditor::buttonCallback(Button* button)
     }
 
 }
+
diff --git a/Source/Processors/RecordNode.cpp b/Source/Processors/RecordNode.cpp
index 0d3bfdf1bfa3c1f2b963681b5c5168e1659995dd..0e79b4d282b08ba11fd68f6a98fc371bf0ba42b7 100755
--- a/Source/Processors/RecordNode.cpp
+++ b/Source/Processors/RecordNode.cpp
@@ -286,7 +286,7 @@ String RecordNode::generateDateString()
 
 void RecordNode::setParameter(int parameterIndex, float newValue)
 {
-    editor->updateParameterButtons(parameterIndex);
+    //editor->updateParameterButtons(parameterIndex);
 
     // 0 = stop recording
     // 1 = start recording
diff --git a/Source/Processors/Visualization/SpikeDisplayCanvas.cpp b/Source/Processors/Visualization/SpikeDisplayCanvas.cpp
index 72f2fe5129241cf1c0762066e3bad0566e79e271..6267bc67ef541043a04a85727d3a8e4ffe088147 100755
--- a/Source/Processors/Visualization/SpikeDisplayCanvas.cpp
+++ b/Source/Processors/Visualization/SpikeDisplayCanvas.cpp
@@ -463,18 +463,18 @@ void SpikePlot::setLimitsOnAxes()
 {
     //std::cout<<"SpikePlot::setLimitsOnAxes()"<<std::endl;
 
-    for (int i = 0; i < nWaveAx; i++)
-        wAxes[i]->setYLims(limits[i][0], limits[i][1]);
-
-    // Each Projection sets its limits using the limits of the two waveform dims it represents.
-    // Convert projection number to indecies, and then set the limits using those indices
-    int j1, j2;
-    for (int i = 0; i < nProjAx; i++)
-    {
-        n2ProjIdx(pAxes[i]->getType(), &j1, &j2);
-        pAxes[i]->setYLims(limits[j1][0], limits[j1][1]);
-        pAxes[i]->setXLims(limits[j2][0], limits[j2][1]);
-    }
+    // for (int i = 0; i < nWaveAx; i++)
+    //     wAxes[i]->setYLims(limits[i][0], limits[i][1]);
+
+    // // Each Projection sets its limits using the limits of the two waveform dims it represents.
+    // // Convert projection number to indecies, and then set the limits using those indices
+    // int j1, j2;
+    // for (int i = 0; i < nProjAx; i++)
+    // {
+    //     n2ProjIdx(pAxes[i]->getType(), &j1, &j2);
+    //     pAxes[i]->setYLims(limits[j1][0], limits[j1][1]);
+    //     pAxes[i]->setXLims(limits[j2][0], limits[j2][1]);
+    // }
 }
 
 void SpikePlot::initLimits()
@@ -558,56 +558,29 @@ void SpikePlot::zoom(int dim, bool in)
 }
 
 
-void SpikePlot::n2ProjIdx(int proj, int* p1, int* p2)
-{
-    int d1, d2;
-    if (proj==PROJ1x2)
-    {
-        d1 = 0;
-        d2 = 1;
-    }
-    else if (proj==PROJ1x3)
-    {
-        d1 = 0;
-        d2 = 2;
-    }
-    else if (proj==PROJ1x4)
-    {
-        d1 = 0;
-        d2 = 3;
-    }
-    else if (proj==PROJ2x3)
-    {
-        d1 = 1;
-        d2 = 2;
-    }
-    else if (proj==PROJ2x4)
-    {
-        d1 = 1;
-        d2 = 3;
-    }
-    else if (proj==PROJ3x4)
-    {
-        d1 = 2;
-        d2 = 3;
-    }
-    else
-    {
-        std::cout<<"Invalid projection:"<<proj<<"! Cannot determine d1 and d2"<<std::endl;
-        *p1 = -1;
-        *p2 = -1;
-        return;
-    }
-    *p1 = d1;
-    *p2 = d2;
-}
+
 
 // --------------------------------------------------
 
 
-WaveAxes::WaveAxes(int channel) : GenericAxes(channel), drawGrid(true)
+WaveAxes::WaveAxes(int channel) : GenericAxes(channel), drawGrid(true), 
+    bufferSize(10), spikeIndex(0), thresholdLevel(0.5f),
+    isOverThresholdSlider(false), isDraggingThresholdSlider(false)
 {
+
+    addMouseListener(this, true);
+
+    thresholdColour = Colours::red;
+
     font = Font("Small Text",10,Font::plain);
+
+    for (int n = 0; n < bufferSize; n++)
+    {
+        SpikeObject so;
+        generateEmptySpike(&so, 4);
+        
+        spikeBuffer.add(so);
+    }
 }
 
 void WaveAxes::paint(Graphics& g)
@@ -617,133 +590,376 @@ void WaveAxes::paint(Graphics& g)
 
     int chan = 0;
 
+    // draw the grid lines for the waveforms
+
+    if (drawGrid)
+        drawWaveformGrid(s.threshold[chan], s.gain[chan], g);
+
+    // draw the threshold line and labels
+    drawThresholdSlider(g);
+
     // if no spikes have been received then don't plot anything
     if (!gotFirstSpike)
     {
         return;
     }
+   
+
+    for (int spikeNum = 0; spikeNum < bufferSize; spikeNum++)
+    {
+
+        if (spikeNum != spikeIndex)
+        {
+            g.setColour(Colours::grey);
+            plotSpike(spikeBuffer[spikeNum], g);
+         }
+
+    }
+
+    g.setColour(Colours::white);
+    plotSpike(spikeBuffer[spikeIndex], g);
+    
+
+    
+
+}
+
+void WaveAxes::plotSpike(const SpikeObject& s, Graphics& g)
+{
 
     float h = getHeight();
-    // draw the grid lines for the waveforms
-    if (drawGrid)
-        drawWaveformGrid(s.threshold[chan], s.gain[chan], g);
 
     //compute the spatial width for each waveform sample
-    float dx = (getWidth()-10)/s.nSamples;
-    float x = 5.0f;
-
+    float dx = (getWidth()-10)/float(spikeBuffer[0].nSamples);
+    
     // type corresponds to channel so we need to calculate the starting
     // sample based upon which channel is getting plotted
-    int	sampIdx = s.nSamples * type; //
-
-    // draw the individual waveform points
-    g.setColour(Colours::white);
+    int sampIdx = 40*type; //spikeBuffer[0].nSamples * type; //
 
     int dSamples = 1;
 
-    for (int i = 0; i < s.nSamples-1; i++)
+
+    float x = 5.0f;
+
+     for (int i = 0; i < s.nSamples-1; i++)
     {
         //std::cout << s.data[sampIdx] << std::endl;
-        g.drawLine(x, h/2 + (s.data[sampIdx]-32768)/100, x+dx, h/2 + (s.data[sampIdx+1]-32768)/100);
+        g.drawLine(x, 
+            h/2 + (s.data[sampIdx]-32768)/100, 
+            x+dx, 
+            h/2 + (s.data[sampIdx+1]-32768)/100);
         sampIdx += dSamples;
         x += dx;
     }
 
-    // draw the threshold line and labels
+}
+
+void WaveAxes::drawThresholdSlider(Graphics& g)
+{
+
+    float h = getHeight()*thresholdLevel;
+
+    g.setColour(thresholdColour);
+    g.drawLine(5.0f, h, getWidth()-5.0f, h);
 
 }
 
 void WaveAxes::drawWaveformGrid(int threshold, int gain, Graphics& g)
 {
-    double voltRange = ylims[1] - ylims[0];
-    double pixelRange = getHeight();
-    //This is a totally arbitrary value that seemed to lok the best for me
-    int minPixelsPerTick = 25;
-    int MAX_N_TICKS = 10;
 
-    int nTicks = pixelRange / minPixelsPerTick;
-    while (nTicks > MAX_N_TICKS)
+    float h = getHeight();
+    float w = getWidth();
+
+    for (int i = 1; i < 10; i++)
     {
-        minPixelsPerTick += 5;
-        nTicks = pixelRange / minPixelsPerTick;
+        g.setColour(Colours::darkgrey);
+
+        g.drawLine(5.0,h/10*i,w-5.0f,h/10*i);
+
     }
 
-    int voltPerTick = (voltRange / nTicks);
+    // double voltRange = ylims[1] - ylims[0];
+    // double pixelRange = getHeight();
+    // //This is a totally arbitrary value that seemed to lok the best for me
+    // int minPixelsPerTick = 25;
+    // int MAX_N_TICKS = 10;
 
-    g.setColour(Colours::red);
-    char cstr[200] = {0};
-    String str;
+    // int nTicks = pixelRange / minPixelsPerTick;
+    // while (nTicks > MAX_N_TICKS)
+    // {
+    //     minPixelsPerTick += 5;
+    //     nTicks = pixelRange / minPixelsPerTick;
+    // }
 
-    double tickVoltage = (double) threshold;
+    // int voltPerTick = (voltRange / nTicks);
 
-    // If the limits are bad we don't want to hang the program trying to draw too many ticks
-    // so count the number of ticks drawn and kill the routine after 100 draws
-    int tickCount=0;
-    while (tickVoltage < ylims[1] - voltPerTick*1.5) // Draw the ticks above the thold line
-    {
-        tickVoltage = (double) roundUp(tickVoltage + voltPerTick, 100);
+    // g.setColour(Colours::red);
+    // char cstr[200] = {0};
+    // String str;
+
+    // double tickVoltage = (double) threshold;
 
-        g.drawLine(0, tickVoltage, s.nSamples, tickVoltage);
+    // // If the limits are bad we don't want to hang the program trying to draw too many ticks
+    // // so count the number of ticks drawn and kill the routine after 100 draws
+    // int tickCount=0;
+    // while (tickVoltage < ylims[1] - voltPerTick*1.5) // Draw the ticks above the thold line
+    // {
+    //     tickVoltage = (double) roundUp(tickVoltage + voltPerTick, 100);
 
-        // glBegin(GL_LINE_STRIP);
-        // glVertex2i(0, tickVoltage);
-        // glVertex2i(s.nSamples, tickVoltage);
-        // glEnd();
+    //     g.drawLine(0, tickVoltage, s.nSamples, tickVoltage);
 
-        makeLabel(tickVoltage, gain, true, cstr);
-        str = String(cstr);
-        g.setFont(font);
-        g.drawText(str, 1, tickVoltage+voltPerTick/10, 100, 15, Justification::left, false);
+    //     // glBegin(GL_LINE_STRIP);
+    //     // glVertex2i(0, tickVoltage);
+    //     // glVertex2i(s.nSamples, tickVoltage);
+    //     // glEnd();
 
-        if (tickCount++>100)
-            return;
+    //     makeLabel(tickVoltage, gain, true, cstr);
+    //     str = String(cstr);
+    //     g.setFont(font);
+    //     g.drawText(str, 1, tickVoltage+voltPerTick/10, 100, 15, Justification::left, false);
+
+    //     if (tickCount++>100)
+    //         return;
+    // }
+
+    // tickVoltage = threshold;
+    // tickCount = 0;
+
+    // while (tickVoltage > ylims[0] + voltPerTick) // draw the ticks below the thold line
+    // {
+    //     tickVoltage = (double) roundUp(tickVoltage - voltPerTick, 100);
+
+    //     g.drawLine(0, tickVoltage, s.nSamples, tickVoltage);
+
+    //     // glBegin(GL_LINE_STRIP);
+    //     // glVertex2i(0, tickVoltage);
+    //     // glVertex2i(s.nSamples, tickVoltage);
+    //     // glEnd();
+
+    //     makeLabel(tickVoltage, gain, true, cstr);
+    //     str = String(cstr);
+    //     g.drawText(str, 1, tickVoltage+voltPerTick/10, 100, 15, Justification::left, false);
+
+    //     if (tickCount++>100)
+    //         return;
+    // }
+}
+
+void WaveAxes::updateSpikeData(const SpikeObject& s)
+{
+    if (!gotFirstSpike)
+    {
+        gotFirstSpike = true;
     }
 
-    tickVoltage = threshold;
-    tickCount = 0;
+    SpikeObject newSpike = s;
 
-    while (tickVoltage > ylims[0] + voltPerTick) // draw the ticks below the thold line
+    spikeBuffer.set(spikeIndex, newSpike);
+
+    spikeIndex++;
+    spikeIndex %= bufferSize;
+
+}
+
+void WaveAxes::clear()
+{
+
+}
+
+void WaveAxes::mouseMove(const MouseEvent& event)
+{
+
+   // Point<int> pos = event.getPosition();
+
+    float y = event.y;
+
+    float h = getHeight()*thresholdLevel;
+
+   // std::cout << y << " " << h << std::endl;
+
+    if (y > h - 10.0f && y < h + 10.0f && !isOverThresholdSlider)
     {
-        tickVoltage = (double) roundUp(tickVoltage - voltPerTick, 100);
+        thresholdColour = Colours::yellow; 
+
+      //  std::cout << "Yes." << std::endl;
+        
+        repaint();
+
+        isOverThresholdSlider = true;
+
+       // cursorType = MouseCursor::DraggingHandCursor;
 
-        g.drawLine(0, tickVoltage, s.nSamples, tickVoltage);
+    } else if ((y < h - 10.0f || y > h + 10.0f) && isOverThresholdSlider){
 
-        // glBegin(GL_LINE_STRIP);
-        // glVertex2i(0, tickVoltage);
-        // glVertex2i(s.nSamples, tickVoltage);
-        // glEnd();
+        thresholdColour = Colours::red;
+        repaint();
 
-        makeLabel(tickVoltage, gain, true, cstr);
-        str = String(cstr);
-        g.drawText(str, 1, tickVoltage+voltPerTick/10, 100, 15, Justification::left, false);
+        isOverThresholdSlider = false;
 
-        if (tickCount++>100)
-            return;
+     //   cursorType = MouseCursor::NormalCursor;
+        
     }
+
+
 }
 
-void WaveAxes::clear()
+void WaveAxes::mouseDown(const MouseEvent& event)
+{
+    // if (isOverThresholdSlider)
+    // {
+    //     cursorType = MouseCursor::DraggingHandCursor;
+    // }
+}
+
+void WaveAxes::mouseDrag(const MouseEvent& event)
+{
+    if (isOverThresholdSlider)
+    {
+        thresholdLevel = float(event.y) / float(getHeight());
+        repaint();
+    }
+}
+
+MouseCursor WaveAxes::getMouseCursor()
 {
+    MouseCursor c = MouseCursor(cursorType);
 
+    return c;
 }
 
+void WaveAxes::mouseExit(const MouseEvent& event)
+{
+    if (isOverThresholdSlider)
+     {
+        isOverThresholdSlider = false;
+        thresholdColour = Colours::red; 
+        repaint();
+    }
+}
 
 // --------------------------------------------------
 
-ProjectionAxes::ProjectionAxes(int projectionNum) : GenericAxes(projectionNum)
+ProjectionAxes::ProjectionAxes(int projectionNum) : GenericAxes(projectionNum), imageDim(500)
 {
+    projectionImage = Image(Image::RGB, imageDim, imageDim, true);
+
+    clear();
+    //Graphics g(projectionImage);
+    //g.setColour(Colours::red);
+    //g.fillEllipse(20, 20, 300, 200);
+    
+    n2ProjIdx(projectionNum, &ampDim1, &ampDim2);
+
 
 }
 
 void ProjectionAxes::paint(Graphics& g)
 {
-    g.setColour(Colours::orange);
-    g.fillRect(5,5,getWidth()-5, getHeight()-5);
+    //g.setColour(Colours::orange);
+    //g.fillRect(5,5,getWidth()-5, getHeight()-5);
+    g.drawImage(projectionImage,
+                5, 5, getWidth()-10, getHeight()-10,
+                0, 250, 250, 250);
+}
+
+void ProjectionAxes::updateSpikeData(const SpikeObject& s)
+{
+    if (!gotFirstSpike)
+    {
+        gotFirstSpike = true;
+    }
+
+    int idx1, idx2;
+    calcWaveformPeakIdx(s, ampDim1, ampDim2, &idx1, &idx2);
+
+    // add peaks to image
+    updateProjectionImage(s.data[idx1], s.data[idx2]);
+
+}
+
+void ProjectionAxes::updateProjectionImage(uint16_t x, uint16_t y)
+{
+    Graphics g(projectionImage);
+
+    float xf = float(x-32768)*(float(imageDim)/32768.0);
+    float yf = float(imageDim) - float(y-32768)*(float(imageDim)/32768.0);
+
+    g.setColour(Colours::white);
+    g.fillEllipse(xf,yf,2.0f,2.0f);
+
+}
+
+void ProjectionAxes::calcWaveformPeakIdx(const SpikeObject& s, int d1, int d2, int* idx1, int* idx2)
+{
+
+    int max1 = -1*pow(2.0,15);
+    int max2 = max1;
+
+    for (int i = 0; i < s.nSamples; i++)
+    {
+        if (s.data[d1*s.nSamples + i] > max1)
+        {
+            *idx1 = d1*s.nSamples+i;
+            max1 = s.data[*idx1];
+        }
+        if (s.data[d2*s.nSamples+i] > max2)
+        {
+            *idx2 = d2*s.nSamples+i;
+            max2 = s.data[*idx2];
+        }
+    }
 }
 
+
+
 void ProjectionAxes::clear()
 {
+    projectionImage.clear(Rectangle<int>(0, 0, projectionImage.getWidth(), projectionImage.getHeight()),
+                         Colours::black);
+}
 
+void ProjectionAxes::n2ProjIdx(int proj, int* p1, int* p2)
+{
+    int d1, d2;
+    if (proj==PROJ1x2)
+    {
+        d1 = 0;
+        d2 = 1;
+    }
+    else if (proj==PROJ1x3)
+    {
+        d1 = 0;
+        d2 = 2;
+    }
+    else if (proj==PROJ1x4)
+    {
+        d1 = 0;
+        d2 = 3;
+    }
+    else if (proj==PROJ2x3)
+    {
+        d1 = 1;
+        d2 = 2;
+    }
+    else if (proj==PROJ2x4)
+    {
+        d1 = 1;
+        d2 = 3;
+    }
+    else if (proj==PROJ3x4)
+    {
+        d1 = 2;
+        d2 = 3;
+    }
+    else
+    {
+        std::cout<<"Invalid projection:"<<proj<<"! Cannot determine d1 and d2"<<std::endl;
+        *p1 = -1;
+        *p2 = -1;
+        return;
+    }
+    *p1 = d1;
+    *p2 = d2;
 }
 
 // --------------------------------------------------
@@ -848,7 +1064,9 @@ void GenericAxes::makeLabel(int val, int gain, bool convert, char* s)
             sprintf(s, "%.2fuV", volt);
     }
     else
+    {
         sprintf(s,"%d", (int)val);
+    }
 }
 
 double GenericAxes::ad16ToUv(int x, int gain)
diff --git a/Source/Processors/Visualization/SpikeDisplayCanvas.h b/Source/Processors/Visualization/SpikeDisplayCanvas.h
index 8c3ede25520095e869ffe33a81af860aa4b77a2d..008703c2a6aaa18bb4149a464f67aaad288dc1a7 100755
--- a/Source/Processors/Visualization/SpikeDisplayCanvas.h
+++ b/Source/Processors/Visualization/SpikeDisplayCanvas.h
@@ -206,7 +206,6 @@ private:
     void setLimitsOnAxes();
     void updateAxesPositions();
 
-    void n2ProjIdx(int i, int* p1, int* p2);
 
     Font font;
 
@@ -228,7 +227,7 @@ public:
 
     virtual ~GenericAxes();
 
-    void updateSpikeData(const SpikeObject& s);
+    virtual void updateSpikeData(const SpikeObject& s);
 
     void setXLims(double xmin, double xmax);
     void getXLims(double* xmin, double* xmax);
@@ -260,7 +259,6 @@ protected:
 };
 
 
-
 /**
 
   Class for drawing spike waveforms.
@@ -273,10 +271,21 @@ public:
     WaveAxes(int channel);
     ~WaveAxes() {}
 
+    void updateSpikeData(const SpikeObject& s);
+
     void paint(Graphics& g);
 
+    void plotSpike(const SpikeObject& s, Graphics& g);
+
     void clear();
 
+    void mouseMove(const MouseEvent& event);
+    void mouseExit(const MouseEvent& event);
+    void mouseDown(const MouseEvent& event);
+    void mouseDrag(const MouseEvent& event);
+
+    MouseCursor getMouseCursor();
+
 private:
 
     Colour waveColour;
@@ -285,14 +294,30 @@ private:
 
     bool drawGrid;
 
+    float thresholdLevel;
+
     void drawWaveformGrid(int threshold, int gain, Graphics& g);
 
+    void drawThresholdSlider(Graphics& g);
+
     Font font;
 
+    Array<SpikeObject> spikeBuffer;
+
+    int spikeIndex;
+    int bufferSize;
+
+    bool isOverThresholdSlider;
+    bool isDraggingThresholdSlider;
+
+    MouseCursor::StandardCursorType cursorType;
+
 };
 
 
 
+
+
 /**
 
   Class for drawing the peak projections of spike waveforms.
@@ -305,15 +330,30 @@ public:
     ProjectionAxes(int projectionNum);
     ~ProjectionAxes() {}
 
+    void updateSpikeData(const SpikeObject& s);
+
     void paint(Graphics& g);
 
     void clear();
 
 private:
 
+    void updateProjectionImage(uint16_t, uint16_t);
+
+    void calcWaveformPeakIdx(const SpikeObject&, int, int, int*, int*);
+
+
+    void n2ProjIdx(int i, int* p1, int* p2);
+
+    int ampDim1, ampDim2;
+
+    Image projectionImage;
+
     Colour pointColour;
     Colour gridColour;
 
+    int imageDim;
+
 };
 
 
diff --git a/Source/UI/UIComponent.cpp b/Source/UI/UIComponent.cpp
index 015d375e5b73c5557df08fad8521e08071c7cf93..34747cb8248b924195079093dcd8ad199231c08f 100755
--- a/Source/UI/UIComponent.cpp
+++ b/Source/UI/UIComponent.cpp
@@ -92,6 +92,8 @@ UIComponent::UIComponent(MainWindow* mainWindow_, ProcessorGraph* pgraph, AudioC
     mainWindow->setMenuBar(this);
 #endif
 
+  //  getEditorViewport()->loadState(File("/home/jsiegle/Programming/GUI/Builds/Linux/build/spike_display.xml"));
+
 }
 
 UIComponent::~UIComponent()