
// Copyright 2016-2021, Will Godfrey

// This file is part of yoshimi, which 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.

// yoshimi 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 yoshimi.  If not, see <http://www.gnu.org/licenses/>.


// generated by Fast Light User Interface Designer (fluid) version 1.0308

#include "VectorUI.h"
#include "MasterUI.h"
#include "Misc/FileMgrFuncs.h"
    using file::findLeafName;
    using file::setExtension;
    using file::isRegularFile;
#include "Misc/NumericFuncs.h"
    using func::bitClear;
    using func::bitTest;
    using func::bitSet;
#include "Misc/TextMsgBuffer.h"

    namespace { // Implementation details...
        TextMsgBuffer& textMsgBuffer = TextMsgBuffer::instance();
    }
#include <vector>
    #include <string>
    using std::vector;
    using std::to_string;

void VectorUI::cb_vectorwindow_i(Fl_Double_Window*, void*) {
  //
      Closevector->do_callback();
}
void VectorUI::cb_vectorwindow(Fl_Double_Window* o, void* v) {
  ((VectorUI*)(o->user_data()))->cb_vectorwindow_i(o,v);
}

void VectorUI::cb_setbasechan_i(WidgetSpinner* o, void*) {
  //
        BaseChan = o->value() - 1;
        updateAll(false);
}
void VectorUI::cb_setbasechan(WidgetSpinner* o, void* v) {
  ((VectorUI*)(o->parent()->user_data()))->cb_setbasechan_i(o,v);
}

void VectorUI::cb_options_i(Fl_Menu_Button* o, void*) {
  int res = o->value();
switch (res)
{
    case 0:
        loadVector("");;
        break;
    case 1:
    {
        bool ok = true;
          int count;
          int size;
          string name;

          if (Xcc < 14)
          {
              alert(synth, "Nothing to save!");
              ok = false;
          }
          else
          {
              count = 0;
              if (Ycc >= 14)
                  size = NUM_MIDI_CHANNELS * 4;
              else
                  size = NUM_MIDI_CHANNELS * 2;
              for (int i = 0; i < size; i += NUM_MIDI_CHANNELS)
              {
                  if (synth->part[BaseChan + i]->Pname != DEFAULT_NAME)
                      count += NUM_MIDI_CHANNELS;
              }
              if (count != size)
              {
                  if (count == 0)
                      name = "No instruments set!";
                  else
                      name = "Only " + to_string(count/NUM_MIDI_CHANNELS) + " of " +  to_string(size/NUM_MIDI_CHANNELS) + " instruments set!";
                  alert(synth, name);
                  ok = false;
              }
          }

          if (ok)
              saveVector();
        break;
    }
    case 2:
        paramsui->Recent->position(vectorwindow->x() + vectorwindow->w() - paramsui->Recent->w(),vectorwindow->y()+20);
        paramsui->Show(TOPLEVEL::XML::Vector);
        break;
    case 3:
        send_data(TOPLEVEL::action::forceUpdate, VECTOR::control::erase, 0, TOPLEVEL::type::Integer, TOPLEVEL::section::vector, UNUSED, UNUSED, UNUSED, BaseChan);
        break;
    case 4:
        send_data(TOPLEVEL::action::forceUpdate, VECTOR::control::erase, 0, TOPLEVEL::type::Integer);
        break;
};
}
void VectorUI::cb_options(Fl_Menu_Button* o, void* v) {
  ((VectorUI*)(o->parent()->user_data()))->cb_options_i(o,v);
}

void VectorUI::cb_XL_i(Fl_Button* o, void*) {
  //
          (void) o; // suppress warning
          synth->getGuiMaster()->activePart = BaseChan;
          bankui->Show();
}
void VectorUI::cb_XL(Fl_Button* o, void* v) {
  ((VectorUI*)(o->parent()->parent()->user_data()))->cb_XL_i(o,v);
}

void VectorUI::cb_XR_i(Fl_Button* o, void*) {
  //
          (void) o; // suppress warning
          synth->getGuiMaster()->activePart = BaseChan + NUM_MIDI_CHANNELS;
          bankui->Show();
}
void VectorUI::cb_XR(Fl_Button* o, void* v) {
  ((VectorUI*)(o->parent()->parent()->user_data()))->cb_XR_i(o,v);
}

void VectorUI::cb_Xfeat1_i(Fl_Choice* o, void*) {
  //
          if (o->value() == 0)
              bitClear(Xf, 0);
          else
              bitSet(Xf, 0);
          send_data(0, VECTOR::control::Xfeature0, o->value(), TOPLEVEL::type::Integer);
}
void VectorUI::cb_Xfeat1(Fl_Choice* o, void* v) {
  ((VectorUI*)(o->parent()->parent()->user_data()))->cb_Xfeat1_i(o,v);
}

void VectorUI::cb_Xfeat2_i(Fl_Choice* o, void*) {
  //
          bitClear(Xf, 1);
          bitClear(Xf, 4);
          if (o->value() >= 1)
          {
              bitSet(Xf, 1);
              if (o->value() == 2)
                  bitSet(Xf, 4);
          }
          send_data(0, VECTOR::control::Xfeature1, o->value(), TOPLEVEL::type::Integer);
}
void VectorUI::cb_Xfeat2(Fl_Choice* o, void* v) {
  ((VectorUI*)(o->parent()->parent()->user_data()))->cb_Xfeat2_i(o,v);
}

void VectorUI::cb_Xfeat3_i(Fl_Choice* o, void*) {
  //
          bitClear(Xf, 2);
          bitClear(Xf, 5);
          if (o->value() >= 1)
          {
              bitSet(Xf, 2);
              if (o->value() == 2)
                  bitSet(Xf, 5);
          }
          send_data(0, VECTOR::control::Xfeature2, o->value(), TOPLEVEL::type::Integer);
}
void VectorUI::cb_Xfeat3(Fl_Choice* o, void* v) {
  ((VectorUI*)(o->parent()->parent()->user_data()))->cb_Xfeat3_i(o,v);
}

void VectorUI::cb_Xfeat4_i(Fl_Choice* o, void*) {
  //
          bitClear(Xf, 3);
          bitClear(Xf, 6);
          if (o->value() >= 1)
          {
              bitSet(Xf, 3);
              if (o->value() == 2)
                  bitSet(Xf, 6);
          }
          send_data(0, VECTOR::control::Xfeature3, o->value(), TOPLEVEL::type::Integer);
}
void VectorUI::cb_Xfeat4(Fl_Choice* o, void* v) {
  ((VectorUI*)(o->parent()->parent()->user_data()))->cb_Xfeat4_i(o,v);
}

void VectorUI::cb_Xcontrol_i(WidgetSpinner* o, void*) {
  //
        int tmp = o->value();
        if (Xcc < 14 && tmp < 14)
            tmp = 14;

        if (tmp < 14)
        {
            Xcc = 0;
            send_data(TOPLEVEL::action::forceUpdate, VECTOR::control::erase, 0, TOPLEVEL::type::Integer, TOPLEVEL::section::vector, UNUSED, UNUSED, UNUSED, BaseChan);
            return;
        }

        string name = synth->getRuntime().masterCCtest(tmp);
        if (name != "")
        {
            errorlabel("CC " + to_string(tmp) +" in use for " + name);
            return;
        }

        Xcc =  tmp;
        send_data(TOPLEVEL::action::forceUpdate, VECTOR::control::Xcontroller, tmp, TOPLEVEL::type::Integer);
}
void VectorUI::cb_Xcontrol(WidgetSpinner* o, void* v) {
  ((VectorUI*)(o->parent()->user_data()))->cb_Xcontrol_i(o,v);
}

void VectorUI::cb_Closevector_i(Fl_Button*, void*) {
  //
            saveWin(synth, vectorwindow->w(), vectorwindow->h(), vectorwindow->x(), vectorwindow->y(), false, "Vector");
        vectorwindow->hide();
        setVisible(synth, false, "Vector");
        vectorSeen = false;
}
void VectorUI::cb_Closevector(Fl_Button* o, void* v) {
  ((VectorUI*)(o->parent()->user_data()))->cb_Closevector_i(o,v);
}

void VectorUI::cb_YU_i(Fl_Button* o, void*) {
  //
          (void) o; // suppress warning
          synth->getGuiMaster()->activePart = BaseChan + NUM_MIDI_CHANNELS * 2;
          bankui->Show();
}
void VectorUI::cb_YU(Fl_Button* o, void* v) {
  ((VectorUI*)(o->parent()->parent()->user_data()))->cb_YU_i(o,v);
}

void VectorUI::cb_YD_i(Fl_Button* o, void*) {
  //
          (void) o; // suppress warning
          synth->getGuiMaster()->activePart = BaseChan + NUM_MIDI_CHANNELS * 3;
          bankui->Show();
}
void VectorUI::cb_YD(Fl_Button* o, void* v) {
  ((VectorUI*)(o->parent()->parent()->user_data()))->cb_YD_i(o,v);
}

void VectorUI::cb_Yfeat1_i(Fl_Choice* o, void*) {
  //
          if (o->value() == 0)
              bitClear(Yf, 0);
          else
              bitSet(Yf, 0);
          send_data(0, VECTOR::control::Yfeature0, o->value(), TOPLEVEL::type::Integer);
}
void VectorUI::cb_Yfeat1(Fl_Choice* o, void* v) {
  ((VectorUI*)(o->parent()->parent()->user_data()))->cb_Yfeat1_i(o,v);
}

void VectorUI::cb_Yfeat2_i(Fl_Choice* o, void*) {
  //
          bitClear(Yf, 1);
          bitClear(Yf, 4);
          if (o->value() >= 1)
          {
              bitSet(Yf, 1);
              if (o->value() == 2)
                  bitSet(Yf, 4);
          }
          send_data(0, VECTOR::control::Yfeature1, o->value(), TOPLEVEL::type::Integer);
}
void VectorUI::cb_Yfeat2(Fl_Choice* o, void* v) {
  ((VectorUI*)(o->parent()->parent()->user_data()))->cb_Yfeat2_i(o,v);
}

void VectorUI::cb_Yfeat3_i(Fl_Choice* o, void*) {
  //
          bitClear(Yf, 2);
          bitClear(Yf, 5);
          if (o->value() >= 1)
          {
              bitSet(Yf, 2);
              if (o->value() == 2)
                  bitSet(Yf, 5);
          }
          send_data(0, VECTOR::control::Yfeature2, o->value(), TOPLEVEL::type::Integer);
}
void VectorUI::cb_Yfeat3(Fl_Choice* o, void* v) {
  ((VectorUI*)(o->parent()->parent()->user_data()))->cb_Yfeat3_i(o,v);
}

void VectorUI::cb_Yfeat4_i(Fl_Choice* o, void*) {
  //
          bitClear(Yf, 3);
          bitClear(Yf, 6);
          if (o->value() >= 1)
          {
              bitSet(Yf, 3);
              if (o->value() == 2)
                  bitSet(Yf, 6);
          }
          send_data(0, VECTOR::control::Yfeature3, o->value(), TOPLEVEL::type::Integer);
}
void VectorUI::cb_Yfeat4(Fl_Choice* o, void* v) {
  ((VectorUI*)(o->parent()->parent()->user_data()))->cb_Yfeat4_i(o,v);
}

void VectorUI::cb_Ycontrol_i(WidgetSpinner* o, void*) {
  //
        int tmp = o->value();
        if (Ycc < 14 && tmp < 14)
            tmp = 14;

        if (tmp < 14)
        {
            Ycc = 0;
            send_data(0, VECTOR::control::Ycontroller, 0xff, TOPLEVEL::type::Integer);
            return;
        }

        string name = synth->getRuntime().masterCCtest(tmp);
        if (name != "")
        {
            errorlabel("CC " + to_string(tmp) +" in use for " + name);
            return;
        }

        Ycc =  tmp;
        send_data(TOPLEVEL::action::forceUpdate, VECTOR::control::Ycontroller, tmp, TOPLEVEL::type::Integer);
}
void VectorUI::cb_Ycontrol(WidgetSpinner* o, void* v) {
  ((VectorUI*)(o->parent()->user_data()))->cb_Ycontrol_i(o,v);
}

void VectorUI::cb_Loaded_i(Fl_Button* o, void*) {
  //
        (void) o; // suppress warning
        string tmp = input_text(synth, "Vector name:", loadlabel[BaseChan]);
        if (tmp != loadlabel[BaseChan])
            send_data(TOPLEVEL::action::lowPrio | TOPLEVEL::action::forceUpdate, VECTOR::control::name, 0, TOPLEVEL::type::Integer, TOPLEVEL::section::vector, UNUSED, UNUSED, UNUSED, BaseChan, textMsgBuffer.push(tmp));
}
void VectorUI::cb_Loaded(Fl_Button* o, void* v) {
  ((VectorUI*)(o->parent()->user_data()))->cb_Loaded_i(o,v);
}

Fl_Double_Window* VectorUI::make_window(void) {
  { Fl_Double_Window* o = vectorwindow = new Fl_Double_Window(375, 295, "Yoshimi : Vectors");
    vectorwindow->labelfont(13);
    vectorwindow->labelsize(12);
    vectorwindow->callback((Fl_Callback*)cb_vectorwindow, (void*)(this));
    vectorwindow->align(Fl_Align(FL_ALIGN_CENTER));
    { WidgetSpinner* o = setbasechan = new WidgetSpinner(121, 12, 38, 20, "Base Channel");
      setbasechan->tooltip("The channel number for this vector");
      setbasechan->box(FL_NO_BOX);
      setbasechan->color(FL_BACKGROUND_COLOR);
      setbasechan->selection_color(FL_BACKGROUND_COLOR);
      setbasechan->labeltype(FL_NORMAL_LABEL);
      setbasechan->labelfont(1);
      setbasechan->labelsize(12);
      setbasechan->labelcolor(FL_FOREGROUND_COLOR);
      setbasechan->maximum(16);
      setbasechan->textsize(12);
      setbasechan->callback((Fl_Callback*)cb_setbasechan);
      setbasechan->align(Fl_Align(FL_ALIGN_LEFT));
      setbasechan->when(FL_WHEN_RELEASE);
      o->value(BaseChan + 1);
    } // WidgetSpinner* setbasechan
    { Fl_Menu_Button* o = options = new Fl_Menu_Button(275, 12, 74, 20, "Options");
      options->labelsize(12);
      options->textsize(12);
      options->callback((Fl_Callback*)cb_options);
      (void) o; // suppress warning
      vector <string> listType = *synth->getHistory(TOPLEVEL::XML::Vector);
      o->add("Load");o->add("Save");o->add("Recent");o->add("Clear Ch");o->add("Clear All");
      setRecent(listType.size() > 0);
    } // Fl_Menu_Button* options
    { Xgroup = new Fl_Group(8, 42, 360, 104, "X");
      Xgroup->box(FL_PLASTIC_THIN_UP_BOX);
      Xgroup->color((Fl_Color)221);
      Xgroup->labelfont(1);
      Xgroup->labelsize(16);
      Xgroup->align(Fl_Align(FL_ALIGN_CENTER));
      Xgroup->deactivate();
      { AddBackL = new Fl_Box(21, 53, 53, 19);
        AddBackL->box(FL_FLAT_BOX);
        AddBackL->color(FL_LIGHT1);
      } // Fl_Box* AddBackL
      { SubBackL = new Fl_Box(74, 53, 53, 19);
        SubBackL->box(FL_FLAT_BOX);
        SubBackL->color(FL_LIGHT1);
      } // Fl_Box* SubBackL
      { PadBackL = new Fl_Box(127, 53, 53, 19);
        PadBackL->box(FL_FLAT_BOX);
        PadBackL->color(FL_LIGHT1);
      } // Fl_Box* PadBackL
      { XinstL = new Fl_Text_Display(20, 69, 160, 1);
        XinstL->box(FL_NO_BOX);
        XinstL->labelsize(12);
        XinstL->textsize(12);
        XinstL->align(Fl_Align(97));
      } // Fl_Text_Display* XinstL
      { XL = new Fl_Button(20, 53, 160, 20);
        XL->tooltip("Part corresponding to joystick \'left\' position");
        XL->box(FL_UP_FRAME);
        XL->color((Fl_Color)51);
        XL->labelsize(12);
        XL->callback((Fl_Callback*)cb_XL);
        XL->align(Fl_Align(FL_ALIGN_CLIP));
      } // Fl_Button* XL
      { AddBackR = new Fl_Box(21, 115, 53, 19);
        AddBackR->box(FL_FLAT_BOX);
        AddBackR->color(FL_LIGHT1);
      } // Fl_Box* AddBackR
      { SubBackR = new Fl_Box(74, 115, 53, 19);
        SubBackR->box(FL_FLAT_BOX);
        SubBackR->color(FL_LIGHT1);
      } // Fl_Box* SubBackR
      { PadBackR = new Fl_Box(127, 115, 53, 19);
        PadBackR->box(FL_FLAT_BOX);
        PadBackR->color(FL_LIGHT1);
      } // Fl_Box* PadBackR
      { XinstR = new Fl_Text_Display(20, 131, 160, 1);
        XinstR->box(FL_NO_BOX);
        XinstR->labelsize(12);
        XinstR->textsize(12);
        XinstR->align(Fl_Align(97));
      } // Fl_Text_Display* XinstR
      { XR = new Fl_Button(20, 115, 160, 20);
        XR->tooltip("Part corresponding to joystick \'right\' position");
        XR->box(FL_UP_FRAME);
        XR->color((Fl_Color)51);
        XR->labelsize(12);
        XR->callback((Fl_Callback*)cb_XR);
        XR->align(Fl_Align(FL_ALIGN_CLIP));
      } // Fl_Button* XR
      { Xfeat = new Fl_Text_Display(233, 101, 97, 14, "Features");
        Xfeat->box(FL_NO_BOX);
        Xfeat->labelfont(1);
        Xfeat->textsize(12);
      } // Fl_Text_Display* Xfeat
      { Fl_Choice* o = Xfeat1 = new Fl_Choice(208, 53, 58, 20, "1");
        Xfeat1->down_box(FL_BORDER_BOX);
        Xfeat1->labelsize(12);
        Xfeat1->textsize(12);
        Xfeat1->callback((Fl_Callback*)cb_Xfeat1);
        Xfeat1->align(Fl_Align(FL_ALIGN_RIGHT));
        o->add("off");o->add("vol");
      } // Fl_Choice* Xfeat1
      { Fl_Choice* o = Xfeat2 = new Fl_Choice(302, 53, 58, 20, "2");
        Xfeat2->down_box(FL_BORDER_BOX);
        Xfeat2->labelsize(12);
        Xfeat2->textsize(12);
        Xfeat2->callback((Fl_Callback*)cb_Xfeat2);
        o->add("off");o->add("pan");o->add("panR");
      } // Fl_Choice* Xfeat2
      { Fl_Choice* o = Xfeat3 = new Fl_Choice(208, 115, 58, 20, "3");
        Xfeat3->down_box(FL_BORDER_BOX);
        Xfeat3->labelsize(12);
        Xfeat3->textsize(12);
        Xfeat3->callback((Fl_Callback*)cb_Xfeat3);
        Xfeat3->align(Fl_Align(FL_ALIGN_RIGHT));
        o->add("off");o->add("filt");o->add("filtR");
      } // Fl_Choice* Xfeat3
      { Fl_Choice* o = Xfeat4 = new Fl_Choice(302, 115, 58, 20, "4");
        Xfeat4->down_box(FL_BORDER_BOX);
        Xfeat4->labelsize(12);
        Xfeat4->textsize(12);
        Xfeat4->callback((Fl_Callback*)cb_Xfeat4);
        o->add("off");o->add("mod");o->add("modR");
      } // Fl_Choice* Xfeat4
      Xgroup->end();
    } // Fl_Group* Xgroup
    { WidgetSpinner* o = Xcontrol = new WidgetSpinner(110, 85, 50, 20, "Controller");
      Xcontrol->tooltip("The MIDI CC this axis reponds to");
      Xcontrol->box(FL_NO_BOX);
      Xcontrol->color(FL_BACKGROUND_COLOR);
      Xcontrol->selection_color(FL_BACKGROUND_COLOR);
      Xcontrol->labeltype(FL_NORMAL_LABEL);
      Xcontrol->labelfont(1);
      Xcontrol->labelsize(12);
      Xcontrol->labelcolor(FL_FOREGROUND_COLOR);
      Xcontrol->minimum(0);
      Xcontrol->maximum(119);
      Xcontrol->value(0);
      Xcontrol->textsize(12);
      Xcontrol->callback((Fl_Callback*)cb_Xcontrol);
      Xcontrol->align(Fl_Align(FL_ALIGN_LEFT));
      Xcontrol->when(FL_WHEN_RELEASE);
      //
        o->value(Xcc);
    } // WidgetSpinner* Xcontrol
    { Closevector = new Fl_Button(310, 265, 57, 20, "Close");
      Closevector->labelfont(13);
      Closevector->labelsize(12);
      Closevector->callback((Fl_Callback*)cb_Closevector);
    } // Fl_Button* Closevector
    { Ygroup = new Fl_Group(8, 152, 360, 104, "Y");
      Ygroup->box(FL_PLASTIC_THIN_UP_BOX);
      Ygroup->color((Fl_Color)221);
      Ygroup->labelfont(1);
      Ygroup->labelsize(16);
      Ygroup->align(Fl_Align(FL_ALIGN_CENTER));
      Ygroup->deactivate();
      { AddBackU = new Fl_Box(21, 163, 53, 19);
        AddBackU->box(FL_FLAT_BOX);
        AddBackU->color(FL_LIGHT1);
      } // Fl_Box* AddBackU
      { SubBackU = new Fl_Box(74, 163, 53, 19);
        SubBackU->box(FL_FLAT_BOX);
        SubBackU->color(FL_LIGHT1);
      } // Fl_Box* SubBackU
      { PadBackU = new Fl_Box(127, 163, 53, 19);
        PadBackU->box(FL_FLAT_BOX);
        PadBackU->color(FL_LIGHT1);
      } // Fl_Box* PadBackU
      { YinstU = new Fl_Text_Display(20, 179, 160, 1);
        YinstU->box(FL_NO_BOX);
        YinstU->labelsize(12);
        YinstU->textsize(12);
        YinstU->align(Fl_Align(97));
      } // Fl_Text_Display* YinstU
      { YU = new Fl_Button(20, 163, 160, 20);
        YU->tooltip("Part corresponding to joystick \'up\' position");
        YU->box(FL_UP_FRAME);
        YU->color((Fl_Color)51);
        YU->labelsize(12);
        YU->callback((Fl_Callback*)cb_YU);
        YU->align(Fl_Align(FL_ALIGN_CLIP));
      } // Fl_Button* YU
      { AddBackD = new Fl_Box(21, 225, 53, 19);
        AddBackD->box(FL_FLAT_BOX);
        AddBackD->color(FL_LIGHT1);
      } // Fl_Box* AddBackD
      { SubBackD = new Fl_Box(74, 225, 53, 19);
        SubBackD->box(FL_FLAT_BOX);
        SubBackD->color(FL_LIGHT1);
      } // Fl_Box* SubBackD
      { PadBackD = new Fl_Box(127, 225, 53, 19);
        PadBackD->box(FL_FLAT_BOX);
        PadBackD->color(FL_LIGHT1);
      } // Fl_Box* PadBackD
      { YinstD = new Fl_Text_Display(20, 241, 160, 1);
        YinstD->box(FL_NO_BOX);
        YinstD->labelsize(12);
        YinstD->textsize(12);
        YinstD->align(Fl_Align(97));
      } // Fl_Text_Display* YinstD
      { YD = new Fl_Button(20, 225, 160, 20);
        YD->tooltip("Part corresponding to joystick \'down\'position");
        YD->box(FL_UP_FRAME);
        YD->color((Fl_Color)51);
        YD->labelsize(12);
        YD->callback((Fl_Callback*)cb_YD);
        YD->align(Fl_Align(FL_ALIGN_CLIP));
      } // Fl_Button* YD
      { Yfeat = new Fl_Text_Display(233, 211, 97, 14, "Features");
        Yfeat->box(FL_NO_BOX);
        Yfeat->labelfont(1);
        Yfeat->textsize(12);
      } // Fl_Text_Display* Yfeat
      { Fl_Choice* o = Yfeat1 = new Fl_Choice(208, 163, 58, 20, "1");
        Yfeat1->down_box(FL_BORDER_BOX);
        Yfeat1->labelsize(12);
        Yfeat1->textsize(12);
        Yfeat1->callback((Fl_Callback*)cb_Yfeat1);
        Yfeat1->align(Fl_Align(FL_ALIGN_RIGHT));
        o->add("off");o->add("vol");
      } // Fl_Choice* Yfeat1
      { Fl_Choice* o = Yfeat2 = new Fl_Choice(302, 163, 58, 20, "2");
        Yfeat2->down_box(FL_BORDER_BOX);
        Yfeat2->labelsize(12);
        Yfeat2->textsize(12);
        Yfeat2->callback((Fl_Callback*)cb_Yfeat2);
        o->add("off");o->add("pan");o->add("panR");
      } // Fl_Choice* Yfeat2
      { Fl_Choice* o = Yfeat3 = new Fl_Choice(208, 225, 58, 20, "3");
        Yfeat3->down_box(FL_BORDER_BOX);
        Yfeat3->labelsize(12);
        Yfeat3->textsize(12);
        Yfeat3->callback((Fl_Callback*)cb_Yfeat3);
        Yfeat3->align(Fl_Align(FL_ALIGN_RIGHT));
        o->add("off");o->add("filt");o->add("filtR");
      } // Fl_Choice* Yfeat3
      { Fl_Choice* o = Yfeat4 = new Fl_Choice(302, 225, 58, 20, "4");
        Yfeat4->down_box(FL_BORDER_BOX);
        Yfeat4->labelsize(12);
        Yfeat4->textsize(12);
        Yfeat4->callback((Fl_Callback*)cb_Yfeat4);
        o->add("off");o->add("mod");o->add("modR");
      } // Fl_Choice* Yfeat4
      Ygroup->end();
    } // Fl_Group* Ygroup
    { WidgetSpinner* o = Ycontrol = new WidgetSpinner(110, 195, 50, 20, "Controller");
      Ycontrol->tooltip("The MIDI CC this axis reponds to");
      Ycontrol->box(FL_NO_BOX);
      Ycontrol->color(FL_BACKGROUND_COLOR);
      Ycontrol->selection_color(FL_BACKGROUND_COLOR);
      Ycontrol->labeltype(FL_NORMAL_LABEL);
      Ycontrol->labelfont(1);
      Ycontrol->labelsize(12);
      Ycontrol->labelcolor(FL_FOREGROUND_COLOR);
      Ycontrol->minimum(0);
      Ycontrol->maximum(119);
      Ycontrol->value(0);
      Ycontrol->textsize(12);
      Ycontrol->callback((Fl_Callback*)cb_Ycontrol);
      Ycontrol->align(Fl_Align(FL_ALIGN_LEFT));
      Ycontrol->when(FL_WHEN_RELEASE);
      Ycontrol->deactivate();
      o->value(Ycc);
    } // WidgetSpinner* Ycontrol
    { Loaded = new Fl_Button(45, 265, 198, 20, "No Name");
      Loaded->tooltip("Last saved or loaded vector file - click to change");
      Loaded->box(FL_THIN_DOWN_BOX);
      Loaded->labelfont(1);
      Loaded->labelsize(12);
      Loaded->callback((Fl_Callback*)cb_Loaded);
    } // Fl_Button* Loaded
    vecDW = o->w();vecDH = o->h();
    o->size_range(vecDW, vecDH, 0, 0, 0, 0, 1);
    vectorwindow->end();
    vectorwindow->resizable(vectorwindow);
  } // Fl_Double_Window* vectorwindow
  return vectorwindow;
}

void VectorUI::send_data(int action, int control, float value, int type, int part , int kit , int engine , int insert , int parameter , int miscmsg ) {
  //
          if (control != 84 && control != 85 && control != VECTOR::control::erase)
          {
              parameter = BaseChan;
          }
          type |= TOPLEVEL::type::Write;
          collect_data(synth, value, action, type, control, part, kit, engine, insert, parameter, UNUSED, miscmsg);
}

void VectorUI::returns_update(CommandBlock *getData) {
  //
      float value = getData->data.value;
      unsigned char control = getData->data.control;
      unsigned char parameter = getData->data.parameter;
      unsigned char miscmsg = getData->data.miscmsg;
      int value_int = lrint(value);
      string msg;
  
      switch (control)
      {
          case VECTOR::control::name:
              msg = textMsgBuffer.fetch(miscmsg);;
              loadlabel[parameter] = msg;
              Loaded->copy_label(msg.c_str());
              break;
  
          case VECTOR::control::Xcontroller:
              if (synth->getGuiMaster()->partmax < NUM_MIDI_CHANNELS * 2)
              {
                  synth->getGuiMaster()->maxparts->value(NUM_MIDI_CHANNELS * 2);
                  synth->getGuiMaster()->partmax = NUM_MIDI_CHANNELS * 2;
                  synth->getGuiMaster()->Panelsmallgroups->show();
              }
              if (value_int < 14 || value_int > 119)
              {
                  Xcc = 0;
                  Ycc = 0;
                  Xgroup->deactivate();
                  Xcontrol->value(0);
                  Ycontrol->value(0);
                  Ygroup->deactivate();
                  Ycontrol->deactivate();
                  Xcontrol->redraw();
                  Ycontrol->redraw();
              }
              else
              {
                  Xgroup->activate();
                  Xcontrol->value(value_int);
                  Xcontrol->redraw();
                  Ycontrol->activate();
                  Xcontrol->redraw();
                  Ycontrol->redraw();
              }
              break;
  
          case VECTOR::control::Xfeature0:
              Xfeat1->value(value_int);
              break;
          case VECTOR::control::Xfeature1:
              Xfeat2->value(value_int);
              break;
          case VECTOR::control::Xfeature2:
              Xfeat3->value(value_int);
              break;
          case VECTOR::control::Xfeature3:
              Xfeat4->value(value_int);
              break;
  
          case VECTOR::control::Ycontroller:
              if (synth->getGuiMaster()->partmax < NUM_MIDI_CHANNELS * 4)
              {
                  synth->getGuiMaster()->maxparts->value(NUM_MIDI_CHANNELS * 4);
                  synth->getGuiMaster()->partmax = NUM_MIDI_CHANNELS * 4;
                  synth->getGuiMaster()->Panelsmallgroups->hide();
                  synth->getGuiMaster()->Panelgroups->show();
              }
              if (value_int < 14 || value_int > 119)
              {
                  Ygroup->deactivate();
                  Ycontrol->value(0);
                  Ycontrol->damage(1);
                  Ycontrol->redraw();
                  Ycc = 0;
              }
              else
              {
                  Ygroup->activate();
                  Ycontrol->value(value_int);
                  Ycontrol->damage(1);
                  Ycontrol->redraw();
              }
              break;
  
          case VECTOR::control::Yfeature0:
              Yfeat1->value(value_int);
              break;
          case VECTOR::control::Yfeature1:
              Yfeat2->value(value_int);
              break;
          case VECTOR::control::Yfeature2:
              Yfeat3->value(value_int);
              break;
          case VECTOR::control::Yfeature3:
              Yfeat4->value(value_int);
              break;
  
          case VECTOR::control::erase:
              if (parameter >= NUM_MIDI_PARTS)
              {
                  for (int i = NUM_MIDI_CHANNELS - 1; i >= 0; --i)
                      clearVector(i);
                  BaseChan = 0;
                  setbasechan->value(1);
              }
              else
                  clearVector(parameter);
              break;
  }
}

void VectorUI::setRecent(bool active) {
  //
      Fl_Menu_Item *m = (Fl_Menu_Item*)options->find_item("Recent");
      if (active)
          m->activate();
      else
          m->deactivate();
}

VectorUI::VectorUI(SynthEngine *_synth, BankUI *_bankui, ParametersUI *_paramsui) {
  //
      synth = _synth;
      bankui = _bankui;
      paramsui = _paramsui;
      BaseChan = 0;
      Xcc = 0;
      Xf = 0;
      Ycc = 0;
      Yf = 0;
      make_window();
      vectorwindow->copy_label(synth->makeUniqueName("Vectors").c_str());
      updateAll();
      vectorSeen = false;
      lastvectorW = 0;
}

VectorUI::~VectorUI() {
  //
          if (vectorSeen)
              saveWin(synth, vectorwindow->w(), vectorwindow->h(), vectorwindow->x(), vectorwindow->y(), true, "Vector");
          vectorwindow->hide();
          delete  vectorwindow;
}

void VectorUI::updateAll(bool everything ) {
  //
      if (everything)
      {
          BaseChan = 0;
          setbasechan->value(BaseChan + 1);
          for (int i = 0; i < NUM_MIDI_CHANNELS; ++i)
              loadlabel[i] = "No Name " + to_string(i + 1);
  
      }
      setInstrumentLabel(BaseChan);
      setInstrumentLabel(BaseChan + NUM_MIDI_CHANNELS);
      setInstrumentLabel(BaseChan + NUM_MIDI_CHANNELS * 2);
      setInstrumentLabel(BaseChan + NUM_MIDI_CHANNELS * 3);
  
      Loaded->copy_label(loadlabel[BaseChan].c_str());
      setbuttons();
      if (Xcontrol->value() >= 14)
          Ycontrol->activate();
      else
          Ycontrol->deactivate();
}

void VectorUI::RefreshChans() {
  //
      for (int i = NUM_MIDI_CHANNELS; i > 0; --i)
      {
          BaseChan = i - 1;
          setInstrumentLabel(BaseChan);
          setInstrumentLabel(BaseChan + NUM_MIDI_CHANNELS);
          setInstrumentLabel(BaseChan + NUM_MIDI_CHANNELS * 2);
          setInstrumentLabel(BaseChan + NUM_MIDI_CHANNELS * 3);
          setbuttons();
          loadlabel[BaseChan] = synth->getRuntime().vectordata.Name[BaseChan];
      }
      Loaded->copy_label(loadlabel[0].c_str());
      setbasechan->value(1);
}

void VectorUI::setbuttons() {
  //
      Xcc = synth->getRuntime().vectordata.Xaxis[BaseChan];
      if (Xcc > 119)
      {
          Xcc = 0;
          Xf = 0;
          Xgroup->deactivate();
          Ycc = 0;
          Yf = 0;
          Ygroup->deactivate();
      }
      else
      {
          Xf = synth->getRuntime().vectordata.Xfeatures[BaseChan];
          Xgroup->activate();
          Ycc = synth->getRuntime().vectordata.Yaxis[BaseChan];
          if (Ycc > 119)
          {
              Ycc = 0;
              Ygroup->deactivate();
          }
          else
          {
              Yf = synth->getRuntime().vectordata.Yfeatures[BaseChan];
              Ygroup->activate();
          }
      }
  
      Xcontrol->value(Xcc);
      if (bitTest(Xf,0))
          Xfeat1->value(1);
      else
          Xfeat1->value(0);
  
      if (bitTest(Xf,4))
          Xfeat2->value(2);
      else if (bitTest(Xf,1))
          Xfeat2->value(1);
      else
          Xfeat2->value(0);
  
      if (bitTest(Xf,5))
          Xfeat3->value(2);
      else if (bitTest(Xf,2))
          Xfeat3->value(1);
      else
          Xfeat3->value(0);
  
      if (bitTest(Xf,6))
          Xfeat4->value(2);
      else if (bitTest(Xf,3))
          Xfeat4->value(1);
      else
          Xfeat4->value(0);
  
      Ycontrol->value(Ycc);
      if (bitTest(Yf,0))
          Yfeat1->value(1);
      else
          Yfeat1->value(0);
  
      if (bitTest(Yf,4))
          Yfeat2->value(2);
      else if (bitTest(Yf,1))
          Yfeat2->value(1);
      else
          Yfeat2->value(0);
  
      if (bitTest(Yf,5))
          Yfeat3->value(2);
      else if (bitTest(Yf,2))
          Yfeat3->value(1);
      else
          Yfeat3->value(0);
  
      if (bitTest(Yf,6))
          Yfeat4->value(2);
      else if (bitTest(Yf,3))
          Yfeat4->value(1);
      else
          Yfeat4->value(0);
}

void VectorUI::Show(SynthEngine *synth) {
  //
      int fetchW, fetchH, fetchX, fetchY, fetchO;
      loadWin(synth, fetchW, fetchH, fetchX, fetchY, fetchO, "Vector");
      vectorwindow->show();
      if (fetchW < vecDW || fetchH < vecDH)
      {
          fetchW = vecDW;
          fetchH = vecDH;
      }
      checkSane(fetchX, fetchY, fetchW, fetchH, vecDW, vecDH, true);
  
      vectorwindow->resize(fetchX, fetchY, fetchW, fetchH);
      vectorSeen = true;
      lastvectorW = 0;
}

void VectorUI::vectorRtext() {
  //
      if (lastvectorW == vectorwindow->w())
          return;
      lastvectorW = vectorwindow->w();
  
      float dW = vectorwindow->w() / vecDW;
      float dH = vectorwindow->h() / vecDH;
      float dScale;
      if (dW < dH)
          dScale = dW;
      else
          dScale = dH;
      if (dScale < 0.2f)
          dScale = 0.2f;
  
      int size12 = int(dScale * 12);
      int size16 = int(dScale * 16);
  
      setbasechan->labelsize(size12);
      setbasechan->textsize(size12);
      options->labelsize(size12);
          options->textsize(size12);
  
      Xgroup->labelsize(size16);
      Xcontrol->labelsize(size12);
          Xcontrol->textsize(size12);
      XinstL->labelsize(size12);
      XinstR->labelsize(size12);
      Xfeat->labelsize(size12);
      Xfeat1->labelsize(size12);
           Xfeat1->textsize(size12);
      Xfeat2->labelsize(size12);
           Xfeat2->textsize(size12);
      Xfeat3->labelsize(size12);
           Xfeat3->textsize(size12);
      Xfeat4->labelsize(size12);
           Xfeat4->textsize(size12);
  
      Ygroup->labelsize(size16);
      Ycontrol->labelsize(size12);
          Ycontrol->textsize(size12);
      YinstU->labelsize(size12);
      YinstD->labelsize(size12);
      Yfeat->labelsize(size12);
      Yfeat1->labelsize(size12);
          Yfeat1->textsize(size12);
      Yfeat2->labelsize(size12);
          Yfeat2->textsize(size12);;
      Yfeat3->labelsize(size12);
          Yfeat3->textsize(size12);
      Yfeat4->labelsize(size12);
          Yfeat4->textsize(size12);
  
      Loaded->labelsize(size12);
      Closevector->labelsize(size12);
  
      vectorwindow->redraw();
}

void VectorUI::setInstrumentLabel(int npart) {
  //
      if ((npart & 0xf) != BaseChan)
          return;
      int engines = findengines(npart);
      int addcol = setcolors(engines & 1);
      int subcol = setcolors(engines & 2);
      int padcol = setcolors(engines & 4);
  
      if (npart == BaseChan)
      {
          AddBackL->damage(1);
          AddBackL->color(addcol);
          SubBackL->damage(1);
          SubBackL->color(subcol);
          PadBackL->damage(1l);
          PadBackL->color(padcol);
          XinstL->copy_label(synth->part[npart]->Pname.c_str());
      }
      else if (npart == BaseChan + NUM_MIDI_CHANNELS)
      {
          AddBackR->damage(1);
          AddBackR->color(addcol);
          SubBackR->damage(1);
          SubBackR->color(subcol);
          PadBackR->damage(1l);
          PadBackR->color(padcol);
          XinstR->copy_label(synth->part[npart]->Pname.c_str());
      }
      else if (npart == BaseChan + NUM_MIDI_CHANNELS * 2)
      {
          AddBackU->damage(1);
          AddBackU->color(addcol);
          SubBackU->damage(1);
          SubBackU->color(subcol);
          PadBackU->damage(1l);
          PadBackU->color(padcol);
          YinstU->copy_label(synth->part[npart]->Pname.c_str());
      }
      else if (npart == BaseChan + NUM_MIDI_CHANNELS * 3)
      {
          AddBackD->damage(1);
          AddBackD->color(addcol);
          SubBackD->damage(1);
          SubBackD->color(subcol);
          PadBackD->damage(1l);
          PadBackD->color(padcol);
          YinstD->copy_label(synth->part[npart]->Pname.c_str());
      }
  
      Loaded->copy_label(loadlabel[BaseChan].c_str());
}

void VectorUI::setLoadLabelRemote(int chan, string name) {
  //
      loadlabel[chan] = name;
      BaseChan = chan;
      setbasechan->value(BaseChan + 1);
      updateAll(false);
}

unsigned int VectorUI::findengines(int npart) {
  //
      unsigned int engine = 0;
  
      for (int i = 0; i < NUM_KIT_ITEMS; ++i)
      {
          if (synth->part[npart]->kit[i].Padenabled)
              engine |= 1;
          if (synth->part[npart]->kit[i].Psubenabled)
              engine |= 2;
          if (synth->part[npart]->kit[i].Ppadenabled)
              engine |= 4;
      }
      return engine;
}

int VectorUI::setcolors(int engine) {
  //
      int col;
      switch(engine)
      {
          case 1:
              col = ADD_COLOUR;
              break;
          case 2:
              col = SUB_COLOUR;
              break;
          case 4:
              col = PAD_COLOUR;
              break;
          default:
              col = BASE_COLOUR;
              break;
      }
      return col;
}

void VectorUI::loadVector(string fname) {
  //
      if (fname.empty())
      {
          fname = setfiler(synth,"", "", false, TOPLEVEL::XML::Vector);
          if (fname.empty())
              return;
      }
      send_data(TOPLEVEL::action::muteAndLoop | TOPLEVEL::action::forceUpdate, MAIN::loadNamedVector, 0, TOPLEVEL::type::Integer, TOPLEVEL::section::main, UNUSED, UNUSED, BaseChan, UNUSED, textMsgBuffer.push(fname));
}

void VectorUI::saveVector() {
  //
      string filename = setfiler(synth,"", "", true, TOPLEVEL::XML::Vector);
      if (filename.empty())
          return;
      int pos = loadlabel[BaseChan].find("No Name");
      if (pos >=0 && pos < 2)
          Loaded->copy_label(findLeafName(filename).c_str());
      send_data(TOPLEVEL::action::lowPrio, MAIN::saveNamedVector, 0, TOPLEVEL::type::Integer, TOPLEVEL::section::main, UNUSED, UNUSED, BaseChan, UNUSED, textMsgBuffer.push(filename));
}

void VectorUI::clearVector(int BaseC) {
  //
      int min = 0;
      int max = NUM_MIDI_CHANNELS;
      if (BaseC < NUM_MIDI_CHANNELS)
      {
          min = BaseC;
          max = BaseC + 1;
      }
      for (int i = min; i < max; ++i)
      {
          loadlabel[i] = "No Name " + to_string(i + 1);
          Loaded->copy_label(loadlabel[i].c_str());
       }
       if (BaseC >= NUM_MIDI_CHANNELS)
       {
           BaseChan = 0;
           setInstrumentLabel(0);
           setInstrumentLabel(NUM_MIDI_CHANNELS);
           setInstrumentLabel(NUM_MIDI_CHANNELS * 2);
           setInstrumentLabel(NUM_MIDI_CHANNELS * 3);
       }
  
       Xcc = 0;
       Xf = 0;
       Xgroup->deactivate();
       Xcontrol->value(0);
       Ycc = 0;
       Yf = 0;
       Ygroup->deactivate();
       Ycontrol->deactivate();
       Ycontrol->value(0);
}

void VectorUI::checkParts(int nval) {
  //
  for (int i = 0; i < NUM_MIDI_CHANNELS; ++i)
  {
      if (nval > NUM_MIDI_CHANNELS * 3)
          Ygroup->activate();
      else
          Ygroup->deactivate();
  
      if (nval > NUM_MIDI_CHANNELS)
          Xgroup->activate();
      else
          Xgroup->deactivate();
  }
}

void VectorUI::errorlabel(string msg) {
  //
              synth->getGuiMaster()->words->copy_label(msg.c_str());
              synth->getGuiMaster()->message->show();
              synth->getGuiMaster()->message->position(Fl::event_x_root() + 16, Fl::event_y_root());
}
