Skip to content
Snippets Groups Projects
  • jsiegle's avatar
    ea8c1c90
    Run astyle to make code format more consistent · ea8c1c90
    jsiegle authored
    To run this in the future, install astyle (sudo apt-get install astyle),
    then enter the following from the top-level project directory:
    
    astyle --options=astyle.options --recursive "./Source/*.cpp" "./Source/*.h"
    
    This will convert tabs to 4 spaces and ensure that brackets are on
    their own lines.
    ea8c1c90
    History
    Run astyle to make code format more consistent
    jsiegle authored
    To run this in the future, install astyle (sudo apt-get install astyle),
    then enter the following from the top-level project directory:
    
    astyle --options=astyle.options --recursive "./Source/*.cpp" "./Source/*.h"
    
    This will convert tabs to 4 spaces and ensure that brackets are on
    their own lines.
SignalChainManager.cpp 13.78 KiB
/*
    ------------------------------------------------------------------

    This file is part of the Open Ephys GUI
    Copyright (C) 2013 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 "SignalChainManager.h"

#include "EditorViewport.h"

#include <iostream>

SignalChainManager::SignalChainManager
(EditorViewport* ev_,
 Array<GenericEditor*, CriticalSection>& editorArray_,
 Array<SignalChainTabButton*, CriticalSection>& signalChainArray_)
    : editorArray(editorArray_), signalChainArray(signalChainArray_),
      ev(ev_), tabSize(30)
{
    topTab = 0;
}

SignalChainManager::~SignalChainManager()
{


}

void SignalChainManager::scrollUp()
{

    std::cout << "Scrolling up." << std::endl;

    if (topTab > 0)
    {
        topTab -= 1;
    }

    refreshTabs();

}

void SignalChainManager::scrollDown()
{

    std::cout << "Scrolling down." << std::endl;

    if (topTab < signalChainArray.size()-4)
    {
        topTab += 1;
    }

    refreshTabs();

}

void SignalChainManager::clearSignalChain()
{
    editorArray.clear();

    while (signalChainArray.size() > 0)
    {
        SignalChainTabButton* t = signalChainArray.remove(signalChainArray.size()-1);
        deleteAndZero(t);
    }

}

void SignalChainManager::createNewTab(GenericEditor* editor)
{

    int index = signalChainArray.size();

    SignalChainTabButton* t = new SignalChainTabButton();
    t->setManager(this);
    t->setEditor(editor);

    ev->addChildComponent(t);
    signalChainArray.add(t);

    editor->tabNumber(signalChainArray.size()-1);
    t->setToggleState(true,false);
    t->setNumber(index);

    index -= topTab;
    ev->leftmostEditor = 0;

    if (signalChainArray.size()-topTab > 4)
    {
        scrollDown();
    }

    refreshTabs();

}

void SignalChainManager::removeTab(int tabIndex)
{

    SignalChainTabButton* t = signalChainArray.remove(tabIndex);
    deleteAndZero(t);

    for (int n = 0; n < signalChainArray.size(); n++)
    {
        int tNum = signalChainArray[n]->getEditor()->tabNumber();

        if (tNum > tabIndex)
        {
            signalChainArray[n]->getEditor()->tabNumber(tNum-1);
            signalChainArray[n]->setNumber(tNum-1);
        }

    }

    if (signalChainArray.size()-topTab < 4)
    {
        scrollUp();
    }

    refreshTabs();

}
void SignalChainManager::refreshTabs()
{
    for (int n = 0; n < signalChainArray.size(); n++)
    {
        if (n >= topTab && n < topTab + 4)
        {
            signalChainArray[n]->setVisible(true);
            signalChainArray[n]->setBounds(6,(tabSize-2)*(n-topTab)+23,tabSize-10,tabSize-10);
        }
        else
        {
            signalChainArray[n]->setVisible(false);
        }
    }

    ev->checkScrollButtons(topTab);

}


void SignalChainManager::updateVisibleEditors(GenericEditor* activeEditor,
                                              int index, int insertionPoint, int action)

{

    enum actions {ADD, MOVE, REMOVE, ACTIVATE, UPDATE};

    // Step 1: update the editor array
    if (action == ADD)
    {
        std::cout << "    Adding editor." << std::endl;
        editorArray.insert(insertionPoint, activeEditor);

    }
    else if (action == MOVE)
    {
        std::cout << "    Moving editors." << std::endl;
        if (insertionPoint < index)
            editorArray.move(index, insertionPoint);
        else if (insertionPoint > index)
            editorArray.move(index, insertionPoint-1);

    }
    else if (action == REMOVE)
    {

        std::cout << "    Removing editor." << std::endl;

        GenericProcessor* p = (GenericProcessor*) editorArray[index]->getProcessor();

        // need to inform the other source that its merger has disappeared
        if (p->isMerger())
        {
            p->switchIO();
            if (p->getSourceNode() != 0)
                p->getSourceNode()->setDestNode(0);
        }

        editorArray.remove(index);

        int t = activeEditor->tabNumber();

        // std::cout << editorArray.size() << " " << t << std::endl;

        bool merger;

        if (editorArray.size() > 0)
        {
            GenericProcessor* p = (GenericProcessor*) editorArray[0]->getProcessor();
            merger = (p->isMerger() && p->stillHasSource());
            if (merger)
            {
                std::cout << "We've got a merger!" << std::endl;
                //p->switchSource();
            }
        }

        if (editorArray.size() > 0 && !merger) // if there are still editors in this chain
        {
            if (t > -1)  // pass on tab
            {
                //      std::cout << "passing on the tab." << std::endl;
                int nextEditor = jmax(0,0);//index-1);
                editorArray[nextEditor]->tabNumber(t);
                signalChainArray[t]->setEditor(editorArray[nextEditor]);
            }

            int nextEditor = jmin(index,editorArray.size()-1);
            activeEditor = editorArray[nextEditor];
            activeEditor->select();
            //activeEditor->grabKeyboardFocus();

        }
        else
        {

            std::cout << "Tab number " << t << std::endl;

            removeTab(t);

            if (signalChainArray.size() > 0) // if there are other chains
            {
                int nextTab = jmin(t,signalChainArray.size()-1);
                activeEditor = signalChainArray[nextTab]->getEditor();
                activeEditor->select();
                signalChainArray[nextTab]->setToggleState(true,false); // send it back to update connections
            }
            else
            {
                activeEditor = 0; // nothing is active
                //  signalChainNeedsSource = true;
            }
        }

    }
    else     //no change
    {

        std::cout << "Activating editor" << std::endl;
    }

    // Step 2: update connections
    if (action != ACTIVATE && action != UPDATE && editorArray.size() > 0)
    {

        std::cout << "Updating connections." << std::endl;

        GenericProcessor* source = 0;
        GenericProcessor* dest = (GenericProcessor*) editorArray[0]->getProcessor();

        dest->setSourceNode(source);

        for (int n = 1; n < editorArray.size(); n++)
        {

            dest = (GenericProcessor*) editorArray[n]->getProcessor();
            source = (GenericProcessor*) editorArray[n-1]->getProcessor();

            dest->setSourceNode(source);
        }

        dest->setDestNode(0);

    }

    // Step 3: check for new tabs
    if (action != ACTIVATE && action != UPDATE)
    {

        std::cout << "Checking for new tabs." << std::endl;

        for (int n = 0; n < editorArray.size(); n++)
        {
            GenericProcessor* p = (GenericProcessor*) editorArray[n]->getProcessor();

            if (p->getSourceNode() == 0)// && editorArray[n]->tabNumber() == -1)
            {

                if (editorArray[n]->tabNumber() == -1)

                {
                    if (!p->isMerger())
                    {
                        std::cout << p->getName() << " has no source node. Creating a new tab." << std::endl;
                        createNewTab(editorArray[n]);
                    }
                }

            }
            else
            {
                if (editorArray[n]->tabNumber() > -1)
                {
                    removeTab(editorArray[n]->tabNumber());
                }

                editorArray[n]->tabNumber(-1); // reset tab status
            }

            if (p->isMerger())
            {
                std::cout << "It's a merger!" << std::endl;
                //createNewTab(editorArray[n]);
            }
        }
    }

    // Step 4: Refresh editors in editor array, based on active editor
    for (int n = 0; n < editorArray.size(); n++)
    {
        editorArray[n]->setVisible(false);
    }

    editorArray.clear();
    std::cout << "Cleared editor array." << std::endl;

    GenericEditor* editorToAdd = activeEditor;

    while (editorToAdd != 0)
    {
        std::cout << "Inserting " << editorToAdd->getName() << " at point 0." << std::endl;

        editorArray.insert(0,editorToAdd);
        GenericProcessor* currentProcessor = (GenericProcessor*) editorToAdd->getProcessor();
        GenericProcessor* source = currentProcessor->getSourceNode();

        if (source != 0)
        {
            std::cout << "Source: " << source->getName() << std::endl;
            // need to switch the splitter somehow
            // if (action == ACTIVATE || action == UPDATE)
            // {
            //  if (source->isSplitter())
            //  {
            //      source->setPathToProcessor(currentProcessor);
            //  }
            // }

            editorToAdd = (GenericEditor*) source->getEditor();


        }
        else
        {

            if (editorToAdd->tabNumber() >= 0)
                signalChainArray[editorToAdd->tabNumber()]->setToggleState(true, false);
            std::cout << "No source found." << std::endl;
            editorToAdd = 0;

        }
    }

    editorToAdd = activeEditor;

    while (editorToAdd != 0)
    {

        GenericProcessor* currentProcessor = (GenericProcessor*) editorToAdd->getProcessor();
        GenericProcessor* dest = currentProcessor->getDestNode();

        if (dest != 0)
        {

            std::cout << "Destination: " << dest->getName() << std::endl;
            editorToAdd = (GenericEditor*) dest->getEditor();
            editorArray.add(editorToAdd);
            std::cout << "Inserting " << editorToAdd->getName() << " at the end." << std::endl;

            if (dest->isMerger())
            {
                std::cout << "It's a merger!" << std::endl;

                if (dest->getSourceNode() != currentProcessor)
                    editorToAdd->switchSource();

            }

        }
        else
        {
            std::cout << "No dest found." << std::endl;
            editorToAdd = 0;
        }


    }

    // Step 5: check the validity of the signal chain
    if (true)
    {
        //action != ACTIVATE) {
        bool enable = true;

        if (editorArray.size() == 1)
        {

            GenericProcessor* source = (GenericProcessor*) editorArray[0]->getProcessor();
            if (source->isSource())
                editorArray[0]->setEnabledState(true);
            else
                editorArray[0]->setEnabledState(false);

        }
        else
        {

            for (int n = 0; n < editorArray.size()-1; n++)
            {
                GenericProcessor* source = (GenericProcessor*) editorArray[n]->getProcessor();
                GenericProcessor* dest = (GenericProcessor*) editorArray[n+1]->getProcessor();

                if (n == 0 && !source->isSource())
                    enable = false;

                editorArray[n]->setEnabledState(enable);

                if (source->canSendSignalTo(dest) && source->enabledState())
                    enable = true;
                else
                    enable = false;

                if (source->isSplitter())
                {
                    if (source->getDestNode() != dest)
                    {
                        //source->switchIO();
                        editorArray[n]->switchDest();
                    }
                }

                if (enable)
                    std::cout << "Enabling node." << std::endl;
                else
                    std::cout << "Not enabling node." << std::endl;

                editorArray[n+1]->setEnabledState(enable);

            }
        }
    }

    // Step 6: inform the tabs that something has changed
    for (int n = 0; n < signalChainArray.size(); n++)
    {
        if (signalChainArray[n]->getToggleState())
        {
            signalChainArray[n]->hasNewConnections(true);
        }
    }

    // Step 7: update all settings
    if (action != ACTIVATE)
    {

        std::cout << "Updating settings." << std::endl;

        Array<GenericProcessor*> splitters;

        for (int n = 0; n < signalChainArray.size(); n++)
        {
            // iterate through signal chains

            GenericEditor* source = signalChainArray[n]->getEditor();
            GenericProcessor* p = source->getProcessor();

            p->update();

            if (p->isSplitter())
            {
                splitters.add(p);
            }

            GenericProcessor* dest = p->getDestNode();

            while (dest != 0)
            {
                // iterate through processors
                dest->update();
                dest = dest->getDestNode();

                if (dest == 0 && splitters.size() > 0)
                {
                    splitters.getFirst()->switchIO();
                    dest = splitters[0]->getDestNode();
                    splitters.remove(0);
                }
            }
        }
    }


    std::cout << "Finished adding new editor." << std::endl << std::endl << std::endl;

}