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

#include "ResonanceUI.h"
// ResonanceUI.cc
// Original ZynAddSubFX author Nasca Octavian Paul
// Copyright (C) 2002-2005 Nasca Octavian Paul
// Copyright 2009-2010, Alan Calvert
// Copyright 2015-2023, 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 2 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 (version 2 or
// later) for more details.

// You should have received a copy of the GNU General Public License along with
// yoshimi; if not, write to the Free Software Foundation, Inc., 51 Franklin
// Street, Fifth Floor, Boston, MA  02110-1301, USA.

// This file is a derivative of the ZynAddSubFX original


#include <cmath>
#include <iostream>
#include "MasterUI.h"
#include "Misc/TextMsgBuffer.h"

    namespace { // Implementation details...
        TextMsgBuffer& textMsgBuffer = TextMsgBuffer::instance();
    }
#include "Misc/NumericFuncs.h"
    using func::power;
using std::to_string;

ResonanceGraph::ResonanceGraph(int x,int y, int w, int h, const char *label):Fl_Box(x,y,w,h,label) {
  //
      respar=NULL;
      cbwidget=NULL;
      applybutton=NULL;
}

void ResonanceGraph::send_data(int action, int control, float value, int type) {
  //
      type |= TOPLEVEL::type::Write;
      collect_writeData(synth, value, action, type, RESONANCE::control::graphPoint, npart, kititem, engine, TOPLEVEL::insert::resonanceGraphInsert, control);
}

void ResonanceGraph::init(Resonance *respar_, Fl_Value_Output *khzvalue_, Fl_Value_Output *dbvalue_, int npart_, int kititem_, int engine_) {
  //
      respar = respar_;
      synth = & respar->getSynthEngine();
      npart = npart_;
      kititem = kititem_;
      engine = engine_;
      khzvalue=khzvalue_;
      dbvalue=dbvalue_;
      oldx=-1;
      khzval=-1;
}

void ResonanceGraph::draw_freq_line(float freq) {
  //
      float freqx = respar->getfreqpos(freq);
      if ((freqx>0.0) && (freqx<1.0))
          fl_line(x() + (int) (freqx * w()), y(), x() + (int) (freqx*w()), y() + h());
}

void ResonanceGraph::draw() {
  //
      int ox=x();
      int oy=y();
      int lx=w();
      int ly=h();
      int i;
      float freqx;
      fl_line_style(0, int(1 * ly/256));

      fl_color(graph_back);
      fl_rectf(ox,oy,lx,ly);

      //draw the lines
      fl_color(graph_resonance_grid);

      fl_line(ox+2,oy+ly/2,ox+lx-2,oy+ly/2);

      freqx=respar->getfreqpos(1000.0);
      if ((freqx>0.0)&&(freqx<1.0))
          fl_line(ox+(int) (freqx*lx),oy, ox+(int) (freqx*lx),oy+ly);

      for (i=1;i<10;i++)
      {
          if (i==1)
          {
              draw_freq_line(i*100.0);
              draw_freq_line(i*1000.0);
          }
          else if (i==5)
          {
              draw_freq_line(i*100.0);
              draw_freq_line(i*1000.0);
          }
          else
          {
              draw_freq_line(i*100.0);
              draw_freq_line(i*1000.0);
          }
      }

      draw_freq_line(10000.0);
      draw_freq_line(20000.0);

      int GY=10;
      if (ly<GY*3)
          GY=-1;
      for (i=1;i<GY;i++)
      {
          int tmp=(int)(ly/(float)GY*i);
          fl_line(ox+2,oy+tmp,ox+lx-2,oy+tmp);
      }

      //draw the data
      fl_line_style(0, int(2 * ly/256));
      fl_color(reson_graph_line);
      float ix = ox;
      int oix = int(ix);
      int iy;
      int ny = oy + ly;
      int oiy;
      float dx = 1.0f / MAX_RESONANCE_POINTS * lx;
      float dy = 128.0 / ly;
      oiy = ny - int(respar->Prespoints[0] / dy);
      for (i = 1; i < MAX_RESONANCE_POINTS; i++)
      {
          ix += dx;
          iy = ny - int(respar->Prespoints[i] / dy);
          fl_line(oix, oiy, ix, iy);
          oix = ix;
          oiy = iy;
      }
      fl_line_style(0, 1);
}

int ResonanceGraph::handle(int event) {
  //
      int x_ = Fl::event_x() - x();
      int y_ = Fl::event_y() - y();
      bool inFrame = false;

      if ((x_ >= 0) && (x_ < w()) && (y_ >= 0) && (y_ < h()))
      {
          khzvalue->value(respar->getfreqx(x_ * 1.0 / w()) / 1000.0);
          dbvalue->value((1.0 - y_ * 2.0 / h()) * respar->PmaxdB);
          inFrame = true;
      }

      if ((event == FL_PUSH) || (event == FL_DRAG))
      {
          unsigned char action = 0;
          if (event != FL_DRAG)
              action = TOPLEVEL::action::forceUpdate;
          int leftbutton = 1;
          if (Fl::event_button() == FL_RIGHT_MOUSE)
              leftbutton = 0;
          if (x_ < 0)
              x_ = 0;
          if (y_ < 0)
              y_ = 0;
          if (x_ >= w())
              x_ = w();
          if (y_ >= h() -1)
              y_ = h() -1;

          if ((oldx < 0) || (oldx == x_))
          {
              int sn = (int)(x_ * 1.0 / w() * MAX_RESONANCE_POINTS);
              int sp=127 - (int)(y_ * 1.0 / h() * 127);
              if (_SYS_::F2B(leftbutton))
              {
                  send_data(action, sn, sp, TOPLEVEL::type::Integer);
              }
              else
              {
                  send_data(action, sn, 64, TOPLEVEL::type::Integer);
              }
          }
          else
          {
              int x1 = oldx;
              int x2 = x_;
              int y1 = oldy;
              int y2 = y_;
              if (oldx > x_)
              {
                  x1 = x_;
                  y1 = y_;
                  x2 = oldx;
                  y2 = oldy;
              }
              for (int i = 0; i < x2 - x1; i++)
              {
                  int sn = (int)((i + x1) * 1.0 / w() * MAX_RESONANCE_POINTS);
                  float yy = (y2 - y1) * 1.0 / (x2 - x1) * i;
                  int sp = 127 - (int)((y1 + yy) / h() * 127);
                  if (leftbutton!=0)
                  {
                      send_data(action, sn, sp, TOPLEVEL::type::Integer);
                  }
                  else
                  {
                      send_data(action, sn, 64, TOPLEVEL::type::Integer);
                  }
              }
          }
          oldx = x_;
          oldy = y_;
          redraw();
      }

      if (event == FL_RELEASE)
      {
          oldx = -1;
          if (cbwidget != NULL)
          {
              cbwidget->do_callback();
          }
      }
      if (!inFrame)
          return 0;

      return(1);
}

void ResonanceUI::cb_resonancewindow_i(ScaleTrackedWindow*, void*) {
  resClose->do_callback();
}
void ResonanceUI::cb_resonancewindow(ScaleTrackedWindow* o, void* v) {
  ((ResonanceUI*)(o->user_data()))->cb_resonancewindow_i(o,v);
}

void ResonanceUI::cb_maxdb_i(mwheel_slider_rev* o, void*) {
  //
            if (Fl::event_button() == 3)
                o->value(2000);
            maxdbvo->do_callback();
            o->selection_color(setSlider(o->value(),2000));
            send_data(0, RESONANCE::control::maxDb, o->value()/100, 0);
}
void ResonanceUI::cb_maxdb(mwheel_slider_rev* o, void* v) {
  ((ResonanceUI*)(o->parent()->parent()->user_data()))->cb_maxdb_i(o,v);
}

void ResonanceUI::cb_maxdbvo_i(Fl_Value_Output* o, void*) {
  //
            o->value(maxdb->value()/100);
}
void ResonanceUI::cb_maxdbvo(Fl_Value_Output* o, void* v) {
  ((ResonanceUI*)(o->parent()->parent()->user_data()))->cb_maxdbvo_i(o,v);
}

void ResonanceUI::cb_centerfreq_i(mwheel_slider_rev* o, void*) {
  //
            if (Fl::event_button() == 3)
                o->value(6400);
            centerfreqvo->do_callback();
            o->selection_color(setSlider(o->value(),6400));
            rg->redraw();
            send_data(0, RESONANCE::control::centerFrequency, o->value()/100, 0);
}
void ResonanceUI::cb_centerfreq(mwheel_slider_rev* o, void* v) {
  ((ResonanceUI*)(o->parent()->parent()->user_data()))->cb_centerfreq_i(o,v);
}

void ResonanceUI::cb_centerfreqvo_i(Fl_Value_Output* o, void*) {
  o->value(10.0 * power<10>(- (1.0f - centerfreq->value()/12700.0f) * 2.0f));
}
void ResonanceUI::cb_centerfreqvo(Fl_Value_Output* o, void* v) {
  ((ResonanceUI*)(o->parent()->parent()->user_data()))->cb_centerfreqvo_i(o,v);
}

void ResonanceUI::cb_octavesfreq_i(mwheel_slider_rev* o, void*) {
  //
            if (Fl::event_button() == 3)
                o->value(6400);
            octavesfreqvo->do_callback();
            o->selection_color(setSlider(o->value(),6400));
            rg->redraw();
            send_data(0, RESONANCE::control::octaves, o->value()/100, 0);
}
void ResonanceUI::cb_octavesfreq(mwheel_slider_rev* o, void* v) {
  ((ResonanceUI*)(o->parent()->parent()->user_data()))->cb_octavesfreq_i(o,v);
}

void ResonanceUI::cb_octavesfreqvo_i(Fl_Value_Output* o, void*) {
  o->value(0.25 + 10.0 *octavesfreq->value()/12700.0);
}
void ResonanceUI::cb_octavesfreqvo(Fl_Value_Output* o, void* v) {
  ((ResonanceUI*)(o->parent()->parent()->user_data()))->cb_octavesfreqvo_i(o,v);
}

void ResonanceUI::cb_clearbutton_i(Fl_Button* o, void*) {
  //
            send_data(TOPLEVEL::action::forceUpdate, RESONANCE::control::clearGraph, o->value(), TOPLEVEL::type::Integer);
}
void ResonanceUI::cb_clearbutton(Fl_Button* o, void* v) {
  ((ResonanceUI*)(o->parent()->parent()->user_data()))->cb_clearbutton_i(o,v);
}

void ResonanceUI::cb_smoothbutton_i(Fl_Button* o, void*) {
  //
            send_data(TOPLEVEL::action::forceUpdate, RESONANCE::control::smoothGraph, o->value(), TOPLEVEL::type::Integer);
}
void ResonanceUI::cb_smoothbutton(Fl_Button* o, void* v) {
  ((ResonanceUI*)(o->parent()->parent()->user_data()))->cb_smoothbutton_i(o,v);
}

void ResonanceUI::cb_rnd1_i(Fl_Button*, void*) {
  //
            send_data(TOPLEVEL::action::forceUpdate, RESONANCE::control::randomType, 0, TOPLEVEL::type::Integer);
}
void ResonanceUI::cb_rnd1(Fl_Button* o, void* v) {
  ((ResonanceUI*)(o->parent()->parent()->user_data()))->cb_rnd1_i(o,v);
}

void ResonanceUI::cb_rnd2_i(Fl_Button*, void*) {
  //
            send_data(TOPLEVEL::action::forceUpdate, RESONANCE::control::randomType, 1, TOPLEVEL::type::Integer);
}
void ResonanceUI::cb_rnd2(Fl_Button* o, void* v) {
  ((ResonanceUI*)(o->parent()->parent()->user_data()))->cb_rnd2_i(o,v);
}

void ResonanceUI::cb_rnd3_i(Fl_Button*, void*) {
  //
            send_data(TOPLEVEL::action::forceUpdate, RESONANCE::control::randomType, 2, TOPLEVEL::type::Integer);
}
void ResonanceUI::cb_rnd3(Fl_Button* o, void* v) {
  ((ResonanceUI*)(o->parent()->parent()->user_data()))->cb_rnd3_i(o,v);
}

void ResonanceUI::cb_p1st_i(Fl_Check_Button2* o, void*) {
  //
            send_data(TOPLEVEL::action::forceUpdate, RESONANCE::control::protectFundamental, o->value(), TOPLEVEL::type::Integer);
}
void ResonanceUI::cb_p1st(Fl_Check_Button2* o, void* v) {
  ((ResonanceUI*)(o->parent()->parent()->user_data()))->cb_p1st_i(o,v);
}

void ResonanceUI::cb_sbutton_i(Fl_Button*, void*) {
  //
            send_data(TOPLEVEL::action::forceUpdate, RESONANCE::control::interpolatePeaks, 0, TOPLEVEL::type::Integer);
}
void ResonanceUI::cb_sbutton(Fl_Button* o, void* v) {
  ((ResonanceUI*)(o->parent()->parent()->user_data()))->cb_sbutton_i(o,v);
}

void ResonanceUI::cb_lbutton_i(Fl_Button*, void*) {
  //
            send_data(TOPLEVEL::action::forceUpdate, RESONANCE::control::interpolatePeaks, 1, TOPLEVEL::type::Integer);
}
void ResonanceUI::cb_lbutton(Fl_Button* o, void* v) {
  ((ResonanceUI*)(o->parent()->parent()->user_data()))->cb_lbutton_i(o,v);
}

void ResonanceUI::cb_cbutton_i(Fl_Button*, void*) {
  //
                synth->getGuiMaster()->getPresetsUi()->Ucopy(npart, kititem, engine, TOPLEVEL::insert::resonanceGroup);
                ;
}
void ResonanceUI::cb_cbutton(Fl_Button* o, void* v) {
  ((ResonanceUI*)(o->parent()->parent()->user_data()))->cb_cbutton_i(o,v);
}

void ResonanceUI::cb_pbutton_i(Fl_Button*, void*) {
  //
                synth->getGuiMaster()->getPresetsUi()->Upaste(npart, kititem, engine, TOPLEVEL::insert::resonanceGroup);
                ;
}
void ResonanceUI::cb_pbutton(Fl_Button* o, void* v) {
  ((ResonanceUI*)(o->parent()->parent()->user_data()))->cb_pbutton_i(o,v);
}

void ResonanceUI::cb_enabled_i(Fl_Check_Button2* o, void*) {
  //
          send_data(TOPLEVEL::action::forceUpdate, RESONANCE::control::enableResonance, o->value(), TOPLEVEL::type::Integer);
}
void ResonanceUI::cb_enabled(Fl_Check_Button2* o, void* v) {
  ((ResonanceUI*)(o->parent()->user_data()))->cb_enabled_i(o,v);
}

void ResonanceUI::cb_applybutton_i(Fl_Button*, void*) {
  //
                send_data(TOPLEVEL::action::forceUpdate, PADSYNTH::control::applyChanges, 1, TOPLEVEL::type::Integer);
}
void ResonanceUI::cb_applybutton(Fl_Button* o, void* v) {
  ((ResonanceUI*)(o->parent()->user_data()))->cb_applybutton_i(o,v);
}

void ResonanceUI::cb_resClose_i(Fl_Button*, void*) {
  //
            if (resSeen)
                saveWin(synth, resonancewindow->w(), resonancewindow->h(), resonancewindow->x(), resonancewindow->y(), false, "Resonance " + to_string(engine));
            resonancewindow->hide();
            resSeen = false;
            if ((Fl::event_button() == 3))
            {
                if (engine == PART::engine::addSynth)
                    synth->getGuiMaster()->partui->adnoteui->ADnoteGlobalParameters->show();
                else
                    synth->getGuiMaster()->partui->padnoteui->padnotewindow->show();
            }
}
void ResonanceUI::cb_resClose(Fl_Button* o, void* v) {
  ((ResonanceUI*)(o->parent()->user_data()))->cb_resClose_i(o,v);
}

ScaleTrackedWindow* ResonanceUI::make_window() {
  { ScaleTrackedWindow* o = resonancewindow = new ScaleTrackedWindow(780, 305, "Resonance");
    resonancewindow->box(FL_FLAT_BOX);
    resonancewindow->color(FL_BACKGROUND_COLOR);
    resonancewindow->selection_color(FL_BACKGROUND_COLOR);
    resonancewindow->labeltype(FL_NO_LABEL);
    resonancewindow->labelfont(0);
    resonancewindow->labelsize(14);
    resonancewindow->labelcolor(FL_FOREGROUND_COLOR);
    resonancewindow->callback((Fl_Callback*)cb_resonancewindow, (void*)(this));
    resonancewindow->align(Fl_Align(FL_ALIGN_TOP));
    resonancewindow->when(FL_WHEN_RELEASE);
    { editor = new Fl_Group(0, 0, 777, 305);
      { Fl_Value_Output* o = khzvalue = new Fl_Value_Output(435, 264, 40, 18, "kHz");
        khzvalue->labelsize(12);
        khzvalue->labelcolor((Fl_Color)64);
        khzvalue->minimum(0.001);
        khzvalue->maximum(48);
        khzvalue->textfont(1);
        khzvalue->textsize(12);
        khzvalue->textcolor((Fl_Color)64);
        khzvalue->align(Fl_Align(FL_ALIGN_RIGHT));
        o->step(0.01, 1);
        //this widget must be before the calling widgets
      } // Fl_Value_Output* khzvalue
      { Fl_Value_Output* o = dbvalue = new Fl_Value_Output(435, 283, 40, 18, "dB");
        dbvalue->labelsize(12);
        dbvalue->labelcolor((Fl_Color)64);
        dbvalue->minimum(-150);
        dbvalue->maximum(150);
        dbvalue->textfont(1);
        dbvalue->textsize(12);
        dbvalue->textcolor((Fl_Color)64);
        dbvalue->align(Fl_Align(FL_ALIGN_RIGHT));
        o->step(0.1, 1);
        //this widget must be before the calling widgets
      } // Fl_Value_Output* dbvalue
      { Fl_Group* o = frame = new Fl_Group(6, 5, 768, 256);
        frame->box(FL_BORDER_BOX);
        rg=new ResonanceGraph(o->x(),o->y(),o->w(),o->h(),"");
        rg->init(respar, khzvalue, dbvalue, npart, kititem, engine);
        rg->show();
        frame->end();
      } // Fl_Group* frame
      { mwheel_slider_rev* o = maxdb = new mwheel_slider_rev(77, 283, 98, 18);
        maxdb->tooltip("The volume range");
        maxdb->type(5);
        maxdb->box(FL_THIN_DOWN_BOX);
        maxdb->color(FL_BACKGROUND_COLOR);
        maxdb->selection_color(FL_BACKGROUND_COLOR);
        maxdb->labeltype(FL_NORMAL_LABEL);
        maxdb->labelfont(0);
        maxdb->labelsize(11);
        maxdb->labelcolor((Fl_Color)64);
        maxdb->minimum(1);
        maxdb->maximum(9000);
        maxdb->step(1);
        maxdb->value(2000);
        maxdb->callback((Fl_Callback*)cb_maxdb);
        maxdb->align(Fl_Align(FL_ALIGN_RIGHT));
        maxdb->when(FL_WHEN_CHANGED);
        o->value(respar->PmaxdB*100);
        o->selection_color(setSlider(respar->PmaxdB,20));
      } // mwheel_slider_rev* maxdb
      { Fl_Value_Output* o = maxdbvo = new Fl_Value_Output(55, 282, 22, 18, "Max dB");
        maxdbvo->tooltip("The Maximum amplitude (dB)");
        maxdbvo->box(FL_THIN_DOWN_BOX);
        maxdbvo->labelsize(12);
        maxdbvo->labelcolor((Fl_Color)64);
        maxdbvo->minimum(1);
        maxdbvo->maximum(127);
        maxdbvo->step(1);
        maxdbvo->value(20);
        maxdbvo->textfont(1);
        maxdbvo->textsize(12);
        maxdbvo->textcolor((Fl_Color)64);
        maxdbvo->callback((Fl_Callback*)cb_maxdbvo);
        o->value(maxdb->value()/100);
      } // Fl_Value_Output* maxdbvo
      { mwheel_slider_rev* o = centerfreq = new mwheel_slider_rev(243, 264, 110, 18);
        centerfreq->tooltip("Shift the center frequency");
        centerfreq->type(5);
        centerfreq->box(FL_THIN_DOWN_BOX);
        centerfreq->color(FL_BACKGROUND_COLOR);
        centerfreq->selection_color(FL_BACKGROUND_COLOR);
        centerfreq->labeltype(FL_NORMAL_LABEL);
        centerfreq->labelfont(0);
        centerfreq->labelsize(11);
        centerfreq->labelcolor((Fl_Color)64);
        centerfreq->maximum(12700);
        centerfreq->step(1);
        centerfreq->callback((Fl_Callback*)cb_centerfreq);
        centerfreq->align(Fl_Align(FL_ALIGN_RIGHT));
        centerfreq->when(FL_WHEN_CHANGED);
        o->value(respar->Pcenterfreq*100);
        o->selection_color(setSlider(respar->Pcenterfreq,64));
      } // mwheel_slider_rev* centerfreq
      { Fl_Value_Output* o = centerfreqvo = new Fl_Value_Output(210, 264, 33, 18, "C.f.");
        centerfreqvo->tooltip("Center Frequency (kHz)");
        centerfreqvo->labelsize(12);
        centerfreqvo->labelcolor((Fl_Color)64);
        centerfreqvo->minimum(1);
        centerfreqvo->maximum(10);
        centerfreqvo->value(1);
        centerfreqvo->textfont(1);
        centerfreqvo->textsize(12);
        centerfreqvo->textcolor((Fl_Color)64);
        centerfreqvo->callback((Fl_Callback*)cb_centerfreqvo);
        centerfreqvo->when(FL_WHEN_CHANGED | FL_WHEN_NOT_CHANGED);
        o->step(0.01, 1);
        o->value(10.0 * power<10>(- (1.0f - centerfreq->value()/12700.0f) * 2.0f));
      } // Fl_Value_Output* centerfreqvo
      { mwheel_slider_rev* o = octavesfreq = new mwheel_slider_rev(243, 283, 110, 18);
        octavesfreq->tooltip("Expand the frequency range");
        octavesfreq->type(5);
        octavesfreq->box(FL_THIN_DOWN_BOX);
        octavesfreq->color(FL_BACKGROUND_COLOR);
        octavesfreq->selection_color(FL_BACKGROUND_COLOR);
        octavesfreq->labeltype(FL_NORMAL_LABEL);
        octavesfreq->labelfont(0);
        octavesfreq->labelsize(11);
        octavesfreq->labelcolor((Fl_Color)64);
        octavesfreq->maximum(12700);
        octavesfreq->step(1);
        octavesfreq->callback((Fl_Callback*)cb_octavesfreq);
        octavesfreq->align(Fl_Align(FL_ALIGN_RIGHT));
        octavesfreq->when(FL_WHEN_CHANGED);
        o->value(respar->Poctavesfreq*100);
        o->selection_color(setSlider(respar->Poctavesfreq,64));
      } // mwheel_slider_rev* octavesfreq
      { Fl_Value_Output* o = octavesfreqvo = new Fl_Value_Output(210, 282, 33, 18, "Oct.");
        octavesfreqvo->tooltip("No. of octaves");
        octavesfreqvo->labelsize(12);
        octavesfreqvo->labelcolor((Fl_Color)64);
        octavesfreqvo->minimum(1);
        octavesfreqvo->maximum(127);
        octavesfreqvo->step(1);
        octavesfreqvo->value(5);
        octavesfreqvo->textfont(1);
        octavesfreqvo->textsize(12);
        octavesfreqvo->textcolor((Fl_Color)64);
        octavesfreqvo->callback((Fl_Callback*)cb_octavesfreqvo);
        octavesfreqvo->when(FL_WHEN_CHANGED | FL_WHEN_NOT_CHANGED);
        o->value(0.25 + 10.0 *octavesfreq->value()/12700.0);
      } // Fl_Value_Output* octavesfreqvo
      { clearbutton = new Fl_Button(507, 264, 66, 15, "Clear");
        clearbutton->tooltip("Clear the resonance function");
        clearbutton->box(FL_PLASTIC_THIN_UP_BOX);
        clearbutton->color((Fl_Color)228);
        clearbutton->labelfont(1);
        clearbutton->labelsize(12);
        clearbutton->labelcolor((Fl_Color)64);
        clearbutton->callback((Fl_Callback*)cb_clearbutton);
      } // Fl_Button* clearbutton
      { smoothbutton = new Fl_Button(507, 283, 66, 18, "Smooth");
        smoothbutton->tooltip("Smooth the resonance function");
        smoothbutton->box(FL_PLASTIC_THIN_UP_BOX);
        smoothbutton->color((Fl_Color)228);
        smoothbutton->labelfont(1);
        smoothbutton->labelsize(12);
        smoothbutton->labelcolor((Fl_Color)64);
        smoothbutton->callback((Fl_Callback*)cb_smoothbutton);
      } // Fl_Button* smoothbutton
      { rnd1 = new Fl_Button(583, 264, 42, 11, "Rnd1");
        rnd1->tooltip("Randomize the resonance function");
        rnd1->box(FL_PLASTIC_THIN_UP_BOX);
        rnd1->color((Fl_Color)228);
        rnd1->labelfont(3);
        rnd1->labelsize(10);
        rnd1->labelcolor((Fl_Color)226);
        rnd1->callback((Fl_Callback*)cb_rnd1);
      } // Fl_Button* rnd1
      { rnd2 = new Fl_Button(583, 277, 42, 11, "Rnd2");
        rnd2->tooltip("Randomize the resonance function");
        rnd2->box(FL_PLASTIC_THIN_UP_BOX);
        rnd2->color((Fl_Color)228);
        rnd2->labelfont(3);
        rnd2->labelsize(10);
        rnd2->labelcolor((Fl_Color)226);
        rnd2->callback((Fl_Callback*)cb_rnd2);
      } // Fl_Button* rnd2
      { rnd3 = new Fl_Button(583, 290, 42, 11, "Rnd3");
        rnd3->tooltip("Randomize the resonance function");
        rnd3->box(FL_PLASTIC_THIN_UP_BOX);
        rnd3->color((Fl_Color)228);
        rnd3->labelfont(3);
        rnd3->labelsize(10);
        rnd3->labelcolor((Fl_Color)226);
        rnd3->callback((Fl_Callback*)cb_rnd3);
      } // Fl_Button* rnd3
      { Fl_Check_Button2* o = p1st = new Fl_Check_Button2(106, 265, 45, 15, " Prot.1st");
        p1st->tooltip("Protect the fundamental frequency (do not damp the first harmonic)");
        p1st->box(FL_NO_BOX);
        p1st->down_box(FL_DOWN_BOX);
        p1st->color(FL_BACKGROUND_COLOR);
        p1st->selection_color((Fl_Color)64);
        p1st->labeltype(FL_NORMAL_LABEL);
        p1st->labelfont(3);
        p1st->labelsize(12);
        p1st->labelcolor((Fl_Color)226);
        p1st->callback((Fl_Callback*)cb_p1st);
        p1st->align(Fl_Align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE));
        p1st->when(FL_WHEN_RELEASE);
        o->value(respar->Pprotectthefundamental);
      } // Fl_Check_Button2* p1st
      { interpk = new Fl_Text_Display(364, 280, 62, 0, "InterpPk");
        interpk->box(FL_NO_BOX);
        interpk->labelsize(12);
        interpk->labelcolor((Fl_Color)64);
        interpk->textsize(12);
        interpk->align(Fl_Align(33));
      } // Fl_Text_Display* interpk
      { Fl_Box* o = new Fl_Box(359, 264, 72, 37);
        o->tooltip("Interpolate the peaks (left button smooth, right button linear)");
        o->box(FL_THIN_DOWN_FRAME);
      } // Fl_Box* o
      { sbutton = new Fl_Button(365, 282, 28, 14, "S");
        sbutton->tooltip("Smooth interpolation");
        sbutton->box(FL_PLASTIC_THIN_UP_BOX);
        sbutton->color((Fl_Color)228);
        sbutton->labelfont(1);
        sbutton->labelsize(12);
        sbutton->labelcolor((Fl_Color)64);
        sbutton->callback((Fl_Callback*)cb_sbutton);
      } // Fl_Button* sbutton
      { lbutton = new Fl_Button(398, 282, 28, 14, "L");
        lbutton->tooltip("Linear interpolation");
        lbutton->box(FL_PLASTIC_THIN_UP_BOX);
        lbutton->color((Fl_Color)228);
        lbutton->labelfont(1);
        lbutton->labelsize(12);
        lbutton->labelcolor((Fl_Color)64);
        lbutton->callback((Fl_Callback*)cb_lbutton);
      } // Fl_Button* lbutton
      { cbutton = new Fl_Button(704, 264, 25, 15, "C");
        cbutton->box(FL_THIN_UP_BOX);
        cbutton->color((Fl_Color)179);
        cbutton->labelfont(1);
        cbutton->labelsize(11);
        cbutton->labelcolor((Fl_Color)197);
        cbutton->callback((Fl_Callback*)cb_cbutton);
      } // Fl_Button* cbutton
      { pbutton = new Fl_Button(747, 264, 25, 15, "P");
        pbutton->box(FL_THIN_UP_BOX);
        pbutton->color((Fl_Color)179);
        pbutton->labelfont(1);
        pbutton->labelsize(11);
        pbutton->labelcolor((Fl_Color)197);
        pbutton->callback((Fl_Callback*)cb_pbutton);
      } // Fl_Button* pbutton
      editor->end();
    } // Fl_Group* editor
    { Fl_Check_Button2* o = enabled = new Fl_Check_Button2(6, 265, 78, 15, " Enable");
      enabled->box(FL_NO_BOX);
      enabled->down_box(FL_DOWN_BOX);
      enabled->color(FL_BACKGROUND_COLOR);
      enabled->selection_color((Fl_Color)64);
      enabled->labeltype(FL_NORMAL_LABEL);
      enabled->labelfont(3);
      enabled->labelsize(12);
      enabled->labelcolor((Fl_Color)226);
      enabled->callback((Fl_Callback*)cb_enabled);
      enabled->align(Fl_Align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE));
      enabled->when(FL_WHEN_RELEASE);
      o->value(respar->Penabled);
    } // Fl_Check_Button2* enabled
    { applybutton = new Fl_Button(630, 264, 68, 37, "Apply");
      applybutton->tooltip("Rebuild PADSynth wavetable to pick up changes");
      applybutton->box(FL_GTK_THIN_UP_BOX);
      applybutton->down_box(FL_THIN_DOWN_BOX);
      applybutton->color((Fl_Color)82);
      applybutton->labelfont(1);
      applybutton->labelsize(12);
      applybutton->labelcolor((Fl_Color)64);
      applybutton->callback((Fl_Callback*)cb_applybutton);
    } // Fl_Button* applybutton
    { resClose = new Fl_Button(704, 283, 69, 18, "Close");
      resClose->tooltip("Right click: also reopen previous");
      resClose->box(FL_THIN_UP_BOX);
      resClose->color((Fl_Color)196);
      resClose->labelsize(12);
      resClose->labelcolor((Fl_Color)64);
      resClose->callback((Fl_Callback*)cb_resClose);
    } // Fl_Button* resClose
    resonancewindow->resizable(resonancewindow);
    resDW = o->w();resDH = o->h();
    resonancewindow->size_range(resDW, resDH, 0, 0, 0, 0, 1);
    resonancewindow->end();
  } // ScaleTrackedWindow* resonancewindow
  return resonancewindow;
}

void ResonanceUI::send_data(int action, int control, float value, int type) {
  //
      int insert;
      if (control == PADSYNTH::control::applyChanges)
          insert = UNUSED;
      else
          insert = TOPLEVEL::insert::resonanceGroup;
      type |= TOPLEVEL::type::Write;
      collect_writeData(synth, value, action, type, control, npart, kititem, engine, insert);
}

void ResonanceUI::returns_update(CommandBlock *getData) {
  //
      float value = getData->data.value;
      unsigned char control = getData->data.control;
      unsigned char eng = getData->data.engine;
      unsigned char insert = getData->data.insert;
      if (eng != engine)
          return;

      if (insert == TOPLEVEL::insert::resonanceGraphInsert)
      {
          rg->draw();
          rg->redraw();
      }
      else
      {
          switch(control)
          {
              case RESONANCE::control::maxDb:
                  maxdb->value(value*100);
                  maxdb->selection_color(setSlider(value,20));
                  maxdbvo->do_callback();
                  break;

              case RESONANCE::control::centerFrequency:
                  centerfreq->value(value*100);
                  centerfreq->selection_color(setSlider(value,64));
                  centerfreqvo->do_callback();
                  rg->redraw();
                  break;

              case RESONANCE::control::octaves:
                  octavesfreq->value(value*100);
                  octavesfreq->selection_color(setSlider(value,64));
                  octavesfreqvo->do_callback();
                  rg->redraw();
                  break;

              case RESONANCE::control::enableResonance:
                  if (_SYS_::F2B(value))
                  {
                      enabled->value(1);
                      editor->activate();
                  }
                  else
                  {
                      enabled->value(0);
                      editor->deactivate();
                  }
                  break;

              case RESONANCE::control::randomType:
                  resonancewindow->redraw();
                  break;

              case RESONANCE::control::interpolatePeaks:
                  resonancewindow->redraw();
                  break;

              case RESONANCE::control::protectFundamental:
                  p1st->value(_SYS_::F2B(value));
                  break;

              case RESONANCE::control::clearGraph:
                  resonancewindow->redraw();
                  break;

              case RESONANCE::control::smoothGraph:
                  resonancewindow->redraw();
                  break;
          }
      }
}

ResonanceUI::ResonanceUI(Resonance *respar_, int npart_, int kititem_, int engine_) {
  //
      respar = respar_;
      synth = & respar->getSynthEngine();
      npart = npart_;
      kititem = kititem_;
      engine = engine_;
      make_window();
      resSeen = false;
      applybutton->hide();
      refresh();
      ;
}

ResonanceUI::~ResonanceUI() {
  //
      if (resSeen)
          saveWin(synth, resonancewindow->w(), resonancewindow->h(), resonancewindow->x(), resonancewindow->y(), true, "Resonance " + to_string(engine));
      resSeen = false;
      resonancewindow->hide();
}

void ResonanceUI::refresh() {
  //
      if (respar->Penabled)
      {
          enabled->value(1);
          editor->activate();
      }
      else
      {
          enabled->value(0);
          editor->deactivate();
      }
      maxdb->value(respar->PmaxdB * 100);
      maxdb->selection_color(setSlider(respar->PmaxdB,20));
      maxdbvo->do_callback();

      centerfreq->value(respar->Pcenterfreq * 100);
      centerfreq->selection_color(setSlider(respar->Pcenterfreq,64));
      centerfreqvo->do_callback();

      octavesfreq->value(respar->Poctavesfreq * 100);
      octavesfreq->selection_color(setSlider(respar->Poctavesfreq,64));
      octavesfreqvo->do_callback();

      p1st->value(respar->Pprotectthefundamental);
      rg->redraw();
}

void ResonanceUI::Show() {
  //
      string tname;
      if (engine == PART::engine::addSynth)
          tname = "AddSynth Resonance";
      else
          tname = "PadSynth Resonance ";
      resonancewindow->copy_label(textMsgBuffer.fetch(collect_readData(synth, textMsgBuffer.push("Resonance"), npart, TOPLEVEL::windowTitle, kititem, engine)).c_str());

      int fetchW, fetchH, fetchX, fetchY, fetchO;
      loadWin(synth, fetchW, fetchH, fetchX, fetchY, fetchO, "Resonance " + to_string(engine));
      if(fetchW < resDW || fetchH < resDH)
      {
          fetchW = resDW;
          fetchH = resDH;
      }
      checkSane(fetchX, fetchY, fetchW, fetchH, resDW, resDH);

      resonancewindow->resize(fetchX, fetchY, fetchW, fetchH);
      resonancewindow->show();
      resonanceRtext();
      resSeen = true;
}

void ResonanceUI::resonanceRtext() {
  //
          float dScale = resonancewindow->w() / resDW;

          if (dScale < 0.2f)
              dScale = 0.2f;

          int size = int(10 * dScale);
          int size11 = int(11 * dScale);
          int size12 = int(12 * dScale);

          khzvalue->labelsize(size12);
              khzvalue->textsize(size12);
          dbvalue->labelsize(size12);
              dbvalue->textsize(size12);
          clearbutton->labelsize(size12);
          smoothbutton->labelsize(size12);
          maxdb->labelsize(size11);
              maxdbvo->textsize(size12);
          centerfreqvo->labelsize(size11);
              centerfreqvo->textsize(size12);
          octavesfreqvo->labelsize(size12);
              octavesfreqvo->textsize(size11);
          rnd1->labelsize(size);
          rnd2->labelsize(size);
          rnd3->labelsize(size);
          p1st->labelsize(size12);
          interpk->labelsize(size12);
          sbutton->labelsize(size12);
          lbutton->labelsize(size12);
          cbutton->labelsize(size11);
          pbutton->labelsize(size11);
          enabled->labelsize(size12);
          applybutton->labelsize(size12);
          resClose->labelsize(size12);

          resonancewindow->redraw();
}
