# data file for the Fltk User Interface Designer (fluid)
version 1.0308
header_name {.h}
code_name {.cc}
comment {BankUI.h} {not_in_source in_header
}

comment {BankUI.cc} {in_source not_in_header
}

comment {Original ZynAddSubFX author Nasca Octavian Paul
Copyright (C) 2002-2005 Nasca Octavian Paul
Copyright 2009-2010, Alan Calvert
Copyright 2014-2024, Will Godfrey & others

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 derivative of original ZynAddSubFX code.

} {selected in_source in_header
}

decl {\#include <unistd.h>} {public local
}

decl {\#include <iostream>} {public local
}

decl {\#include <string>
    using std::string;} {public local
}

decl {\#include <FL/Fl_Button.H>} {public local
}

decl {\#include <FL/Fl_Spinner.H>} {public local
}

decl {\#include "UI/MiscGui.h"} {public local
}

decl {\#include "UI/WidgetCheckButton.h"} {public local
}

decl {\#include "UI/WidgetSpinner.h"} {public global
}

decl {\#include "Misc/Bank.h"} {public local
}

decl {\#include "Misc/Config.h"} {public local
}

decl {\#include "Misc/SynthEngine.h"} {public local
}

decl {\#include "Interface/TextLists.h"} {public local
}

decl {\#include "MasterUI.h"} {private local
}
decl {\#include "UI/Themes.h"} {private local
}

decl {\#include "Misc/FormatFuncs.h"
    using func::string2int;
    using func::asString;} {private local
}

decl {\#include "Misc/TextMsgBuffer.h"

    namespace { // Implementation details...
        TextMsgBuffer& textMsgBuffer = TextMsgBuffer::instance();
    }} {private local
}

decl {using std::to_string;} {private global
}

class BankProcess_ {} {
  Function {process()} {return_type {virtual void}
  } {
    code {;} {}
  }
  decl {Bank *bank;} {public local
  }
}

class BankSlot {: {public Fl_Button, BankProcess_}
} {
  Function {BankSlot(int x,int y, int w, int h, const char *label=0):Fl_Button(x,y,w,h,label)} {} {
    code {//
    what = NULL;
    whatslot = NULL;
    nslot = 0;
    nselected = NULL;} {}
  }
  Function {handle(int event)} {return_type int
  } {
    code {//
    if (what == NULL)
        return 0;
    if (Fl::event_inside(this))
    {
        *what = 0;
        *whatslot = nslot;
        if (event == FL_RELEASE)
            *what = Fl::event_button();
        if (event == FL_PUSH)
            highlight = 1;
    }
    else
        highlight = 0;
    int tmp = Fl_Button::handle(event);
    if (*what != 0 && Fl::event_inside(this))
        (bp->*fnc)();
    return tmp;} {}
  }
  Function {init(int nslot_, int *what_, int *whatslot_, void (BankProcess_:: *fnc_)(void), BankProcess_ *bp_, Bank *bank_, int *nselected_)} {} {
    code {//
        nslot = nslot_;
        what = what_;
        whatslot = whatslot_;
        fnc = fnc_;
        bp = bp_;
        bank = bank_;
        nselected = nselected_;
        box(FL_THIN_UP_FRAME);
        labelfont(0);
        labelsize(13);
        labelcolor(gen_text);
        align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE|FL_ALIGN_CLIP);
        highlight = 0;} {}
  }
  Function {refresh(int bk, int rt, int last)} {} {
    code {//
    string instrName = bank->getnamenumbered(nslot, bk, rt);
    copy_label(instrName.c_str());
    rootID = rt;
    bankID = bk;
    lastSeen = last;
    if (bank->engines_used(rt, bk, nslot) & 8)
        labelcolor(yoshi_ins_typ);
    else
        labelcolor(gen_text);} {}
  }
  decl {int *what, *whatslot, nslot, highlight, *nselected;} {private local
  }
  decl {void (BankProcess_:: *fnc)(void);} {private local
  }
  decl {BankProcess_ *bp;} {private local
  }
  Function {draw()} {
    comment {overrides button's draw()} protected
  } {
    code {//
    if (type() == FL_HIDDEN_BUTTON) return;
    int acol, scol, pcol;
    int wid = w() * 0.334;
    int engine = bank->engines_used(rootID, bankID, nslot);
    if (engine > 0)
    {
        acol = bank_back_used; // occupied background
        scol = bank_back_used;
        pcol = bank_back_used;
    }
    else
    {
        acol = bank_back; // normal background
        scol = bank_back;
        pcol = bank_back;
    }

    if (*nselected == nslot)
    {
        acol = bank_swap_back; // selected item background
        scol = bank_swap_back;
        pcol = bank_swap_back;
    }
    else
    {
        if (engine & 1)
            acol = add_back;

        if (engine & 2)
            scol = sub_back;

        if (engine & 4)
            pcol = pad_back;

        if ((lastSeen & 0x7f) == rootID && ((lastSeen >> 8) & 0x7f) == bankID  && ((lastSeen >> 15) == nslot))
            labelfont(1);
        else
            labelfont(0);
    }
    draw_box(FL_FLAT_BOX, x(), y(), wid, h(), (Fl_Color) acol);
    draw_box(FL_FLAT_BOX, x() + wid, y(), wid, h(), (Fl_Color) scol);
    draw_box(FL_FLAT_BOX, x() + wid * 2, y(), wid, h(), (Fl_Color) pcol);

    //frame for label
    draw_box(value() ? (down_box() ? down_box() : fl_down(box())) : box(), x(), y(), w(), h(), Fl_Color(17));

    labelcolor(bank_text);
        draw_label();

    if (Fl::focus() == this) draw_focus();} {}
  }
  decl {int rootID;} {private local
  }
  decl {int bankID;} {private local
  }
  decl {int lastSeen;} {public local
  }
}

class RootProcess_ {} {
  Function {rootprocess()} {return_type {virtual void}
  } {
    code {;} {}
  }
  decl {Bank *root;} {public local
  }
}

class RootSlot {: {public Fl_Button, RootProcess_}
} {
  Function {RootSlot(int x,int y, int w, int h, const char *label=0):Fl_Button(x,y,w,h,label)} {} {
    code {//
    what = NULL;
    whatslot = NULL;
    nslot = 0;
    nselected = NULL;} {}
  }
  Function {handle(int event)} {return_type int
  } {
    code {//
    if (what == NULL)
        return 0;
    if (Fl::event_inside(this))
    {
        *what = 0;
        *whatslot = nslot;
        if (event == FL_RELEASE)
            *what = Fl::event_button();
        if (event == FL_PUSH)
            highlight = 1;
    }
    else
        highlight = 0;

    int tmp = Fl_Button::handle(event);
    if (*what != 0 && Fl::event_inside(this))
        (rp->*fnr)();
    return tmp;} {}
  }
  Function {init(int nslot_, int *what_, int *whatslot_, void (RootProcess_:: *fnr_)(void), RootProcess_ *rp_, Bank *root_, int *rselected_)} {} {
    code {//
        nslot = nslot_;
        what = what_;
        whatslot = whatslot_;
        fnr = fnr_;
        rp = rp_;
        root = root_;
        rselected = rselected_;
        box(FL_THIN_UP_BOX);
        labelfont(0);
        labelcolor(gen_text);
        labelsize(13);
        align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE|FL_ALIGN_CLIP);
        highlight = 0;} {}
  }
  Function {rootrefresh(unsigned int currentBank, unsigned int rootID)} {} {
    code {//
        string bankName = root->getBankName(nslot, rootID);
        if (bankName.empty())
            color(bank_back);
        else
        {
             bankName = std::to_string(nslot) + ". " + bankName;
             if ((unsigned int) nslot == currentBank)
                color(bank_highlight);
            else
                color(bank_back_used);
            if (*rselected == nslot)
                color(bank_swap_back);
        }
        labelcolor(bank_text);
        copy_label(bankName.c_str());} {}
  }
  decl {int *what, *whatslot, nslot, highlight, *nselected, *rselected;} {private local
  }
  decl {void (RootProcess_:: *fnr)(void);} {private local
  }
  decl {RootProcess_ *rp;} {private local
  }
}

class BankUI {: {public BankProcess_, RootProcess_}
} {
  Function {make_window()} {} {
    Fl_Window instrumentuiwindow {
      label Bank
      callback {Hide(0);}
      xywh {687 245 780 570} type Double labelsize 12 labelcolor 64 hide resizable
      code0 {instDW = o->w(), instDH = o->h();}
      code1 {o->size_range((instDW * 8 / 10), (instDH * 8 / 10), 0,0,0,0,1);}
    } {
      Fl_Choice banklist {
        callback {//
        int n = o->value();
        if (n < 0)
            return;

        const Fl_Menu_Item &item = o->menu()[n];
        int nbank = reinterpret_cast<long>(item.user_data());
        send_data(TOPLEVEL::action::lowPrio | TOPLEVEL::action::forceUpdate, BANK::control::selectBank, nbank, TOPLEVEL::type::Integer, TOPLEVEL::section::bank);}
        xywh {5 8 199 20} down_box BORDER_BOX selection_color 7 labelfont 1 labelsize 12 labelcolor 64 align 0 textsize 12 textcolor 64
      } {}
      Fl_Button B_search {
        label Search
        callback {//
            ShowSearch();}
        tooltip {Select instrument from list, by type} xywh {230 5 93 25} box GTK_THIN_UP_BOX color 198 labelfont 1 labelsize 12 labelcolor 64 align 128
      }
      Fl_Button insRoots {
        label Roots
        callback {//
        ShowRoot();
        if ((Fl::event_button() == 3))
        {
            rootFrom = 3;
            Hide(0);
            setVisible(synth, false, "Bank-instrument");
        }
        instFrom = 0;}
        tooltip {Show root paths. Right click: also close this} xywh {364 5 93 25} box GTK_THIN_UP_BOX color 198 labelfont 1 labelsize 12 labelcolor 64 align 128
      }
      Fl_Button insBanks {
        label Banks
        callback {//
        Showbank();
        if ((Fl::event_button() == 3))
        {
            bankFrom = 3;
            Hide(0);
            setVisible(synth, false, "Bank-instrument");
        }
        instFrom = 0;}
        tooltip {Show banks in current root. Right click: also close this} xywh {496 5 93 25} box GTK_THIN_UP_BOX color 198 labelfont 1 labelsize 12 labelcolor 64 align 128
      }
      Fl_Text_Display insT1 {
        label {This column uses MIDI}
        xywh {624 17 136 3} box NO_BOX labelsize 12 labelcolor 64 align 33
      }
      Fl_Text_Display insT2 {
        label {Extended Program Change}
        xywh {610 30 162 3} box NO_BOX labelsize 12 labelcolor 64 align 33
      }
      Fl_Group insgroup {
        xywh {1 31 779 494} labelsize 12
      } {
        Fl_Group insframe1 {
          xywh {4 31 158 494} labelsize 12
          code0 {o->box(FL_NO_BOX);}
          code1 {for (int i = 0; i < 32; ++i)
            {
                bs[i] = new BankSlot (0, 0, o->w(), 15, " ");
                bs[i]->init(i, &what, &slot, &BankProcess_::process,
                            (BankProcess_ *)this, bank, &nselected);
            }}
        } {}
        Fl_Group insframe2 {
          xywh {161 31 152 494} labelsize 12
          code0 {o->box(FL_NO_BOX);}
          code1 {for (int i = 32; i < 64; ++i)
            {
                bs[i] = new BankSlot (0, 0, o->w(), 15, " ");
                bs[i]->init(i, &what, &slot, &BankProcess_::process,
                            (BankProcess_ *)this, bank, &nselected);
            }}
        } {}
        Fl_Group insframe3 {
          xywh {316 31 150 494} labelsize 12
          code0 {o->box(FL_NO_BOX);}
          code1 {for (int i = 64; i < 96; ++i)
            {
                bs[i] = new BankSlot (0, 0, o->w(), 15, " ");
                bs[i]->init(i, &what, &slot, &BankProcess_::process,
                            (BankProcess_ *)this, bank, &nselected);
            }}
        } {}
        Fl_Group insframe4 {
          xywh {469 31 150 494} labelsize 12
          code0 {o->box(FL_NO_BOX);}
          code1 {for (int i = 96; i < 128; ++i)
            {
                bs[i] = new BankSlot (0, 0, o->w(), 15, " ");
                bs[i]->init(i, &what, &slot, &BankProcess_::process,
                            (BankProcess_ *)this, bank, &nselected);
            }}
        } {}
        Fl_Group insframe5 {
          xywh {622 31 156 494} color 48 labelsize 12
          code0 {o->box(FL_NO_BOX);}
          code1 {for (int i = 128; i < 160; ++i)
            {
                bs[i] = new BankSlot (0, 0, o->w(), 15, " ");
                bs[i]->init(i, &what, &slot, &BankProcess_::process,
                            (BankProcess_ *)this, bank, &nselected);
            }}
        } {}
      }
      Fl_Group modeselect {
        xywh {5 528 458 42} box GTK_THIN_UP_BOX labelsize 12
      } {
        Fl_Box selectPatch {
          xywh {11 555 83 9} box RFLAT_BOX color 103 labelcolor 49
        }
        Fl_Button readbutton {
          label SELECT
          callback {//
              setHighlight(1);

          removeselection();}
          xywh {10 534 85 25} box PLASTIC_UP_BOX down_box PLASTIC_UP_BOX color 228 labelfont 9 labelsize 12 labelcolor 64
        }
        Fl_Box renamePatch {
          xywh {100 555 83 9} box RFLAT_BOX color 208 labelcolor 49
        }
        Fl_Button renamebutton {
          label RENAME
          callback {//
              setHighlight(5);
          removeselection();}
          xywh {100 534 85 25} box PLASTIC_UP_BOX down_box PLASTIC_UP_BOX color 228 labelfont 9 labelsize 12 labelcolor 64
        }
        Fl_Box savePatch {
          xywh {190 555 83 9} box RFLAT_BOX color 173 labelcolor 49
        }
        Fl_Button writebutton {
          label SAVE
          callback {//
              setHighlight(2);
          removeselection();}
          xywh {190 534 85 24} box PLASTIC_UP_BOX down_box PLASTIC_UP_BOX color 228 labelfont 9 labelsize 12 labelcolor 64
        }
        Fl_Box deletPatch {
          xywh {280 555 83 9} box RFLAT_BOX color 88 labelcolor 49
        }
        Fl_Button clearbutton {
          label DELETE
          callback {//
              setHighlight(3);
          removeselection();}
          xywh {280 534 85 25} box PLASTIC_UP_BOX down_box PLASTIC_UP_BOX color 228 labelfont 9 labelsize 12 labelcolor 64
        }
        Fl_Box swapPatch {
          xywh {370 555 83 9} box RFLAT_BOX color 176 labelcolor 49
        }
        Fl_Button swapbutton {
          label SWAP
          callback {//
              setHighlight(4);
          removeselection();}
          xywh {370 534 85 25} box PLASTIC_UP_BOX down_box PLASTIC_UP_BOX color 228 labelfont 9 labelsize 12 labelcolor 64
        }
      }
      Fl_Text_Display insT3 {
        label {Engine Types Used}
        xywh {495 546 96 3} box NO_BOX labelsize 12 labelcolor 64 align 33 textsize 12
      }
      Fl_Button insClose {
        label Close
        callback {//
        if (Fl::event_button() == 3)
        {
            if (instFrom == 2)
            {
                bankFrom = 3;
                Showbank();
            }
            else if (instFrom == 4)
            {
                ; // todo open mixer panel
            }
        }
        instFrom = 0; // to avoid later confusion!
        Hide(0);
        saveWin(synth, instrumentuiwindow->w(), instrumentuiwindow->h(), instrumentuiwindow->x(), instrumentuiwindow->y(), false, "Bank-instrument");}
        tooltip {Right click: also reopen previous} xywh {665 539 70 24} box THIN_UP_BOX color 196 labelsize 12 labelcolor 64
      }
      Fl_Group {} {
        xywh {468 528 151 42} box ENGRAVED_FRAME labelsize 12 labelcolor 64
      } {
        Fl_Box addpatch {
          label Add
          xywh {475 550 46 16} box FLAT_BOX labelsize 12 labelcolor 64 align 32
          code0 {o->color(add_back);}
        }
        Fl_Box subpatch {
          label Sub
          xywh {520 550 47 16} box FLAT_BOX labelsize 12 labelcolor 64 align 32
          code0 {o->color(sub_back);}
        }
        Fl_Box padpatch {
          label Pad
          xywh {567 550 46 16} box FLAT_BOX color 29 labelsize 12 labelcolor 64 align 32
          code0 {o->color(pad_back);}
        }
        Fl_Button {} {
          xywh {474 549 139 17} box THIN_UP_FRAME labelsize 12 labelcolor 64
        }
      }
    }
    Fl_Window searchwin {
      label {Yoshimi : Bank Search}
      callback {Hide(3);}
      xywh {1044 153 305 485} type Double box PLASTIC_THIN_UP_BOX color 22 labelsize 12 hide resizable
      code0 {searchDW = o->w(); searchDH = o->h();}
      code1 {searchwin->size_range(searchDW, searchDH, 0, 0, 0, 0, 1);}
    } {
      Fl_Browser searchbrowse {
        callback {//
        if (!o->value())
            return;
        int result = o->value();
        if (result < 0)
            return;
        string line = string(o->text(result));
        int root = string2int(line.substr(0, 3));
        int bank = string2int(line.substr(5, 3));
        int inst = (string2int(line.substr(10, 3))) - 1;
            send_data(TOPLEVEL::action::forceUpdate, MAIN::control::loadInstrumentFromBank, inst, TOPLEVEL::type::Integer, TOPLEVEL::section::main, synth->getGuiMaster()->npart, bank, root);}
        xywh {12 65 282 374} type Select labelsize 12 labelcolor 64 textsize 12 textcolor 64
      }
      Fl_Button searchClose {
        label Close
        callback {//
        Hide(3);}
        xywh {228 451 65 24} color 196 labelsize 12 labelcolor 64 align 192
      }
      Fl_Button searchT {
        label {Root Bank Instrument}
        xywh {12 40 282 4} box NO_BOX labelfont 1 labelsize 12 labelcolor 64 align 6
      }
      Fl_Text_Display noEntries {
        label {No Entries}
        xywh {70 195 177 0} labelfont 1 labelsize 30 labelcolor 129 textsize 12 hide deactivate
      }
      Fl_Group {} {
        xywh {25 1 210 35} labelsize 12
      } {
        Fl_Choice searchType {
          label {Type:}
          callback {//
          searchbrowse->clear();
          int result = o->value();
          if (result >= 0)
          {
              fillBrowser(result);
              noEntries->hide();
          }
          else
              noEntries->show();}
          xywh {70 15 159 20} down_box BORDER_BOX labelfont 1 labelsize 12 labelcolor 64 textfont 1 textsize 12 textcolor 64
          code0 {fillSearchChoice();}
        } {}
      }
    }
    Fl_Window bankuiwindow {
      label Root
      callback {Hide(1);}
      xywh {794 24 780 570} type Double labelsize 12 labelcolor 64 hide resizable
      code0 {o->copy_label(bank->getRootFileTitle(fetchData(0, BANK::control::selectRoot, TOPLEVEL::section::bank)).c_str());}
      code1 {bankDW = o->w();bankDH = o->h();}
      code2 {o->size_range((instDW * 8 / 10), (instDH * 8 / 10), 0,0,0,0,1);}
    } {
      Fl_Button bankroot {
        label Roots
        callback {//
        ShowRoot();
        if ((Fl::event_button() == 3))
        {
            rootFrom = 2;
            Hide(1);
        }
        else
            rootFrom = 0;}
        tooltip {Show root paths. Right click: also close this} xywh {248 5 93 25} box GTK_THIN_UP_BOX color 198 labelfont 1 labelsize 12 labelcolor 64 align 128
      }
      Fl_Button bankcurrent {
        label {current bank}
        tooltip {Show instruments in current bank} xywh {394 10 178 15} box THIN_UP_BOX down_box THIN_UP_BOX color 252 selection_color 252 labelsize 12 labelcolor 64 align 128
      }
      Fl_Button bankinst {
        label Instruments
        callback {//
        instFrom = 2;
        ShowInst();
        if (Fl::event_button() == 3)
        {
            Hide(1);}}
        tooltip {Show instruments in current bank. Right click: also close this} xywh {627 5 93 25} box GTK_THIN_UP_BOX color 198 labelfont 1 labelsize 12 labelcolor 64 align 128
      }
      Fl_Group bankgroup {
        xywh {2 30 776 499} labelsize 12
      } {
        Fl_Group {} {
          xywh {4 30 192 496} labelsize 12
          code0 {o->box(FL_NO_BOX);}
          code1 {//
            for (int i = 0; i < 32; ++i)
            {
                rs[i] = new RootSlot (0, 0, o->w(), 15, " ");
                rs[i]->init(i, &what, &slot, &RootProcess_::rootprocess,
                            (RootProcess_ *)this, bank, &rselected);

          }}
        } {}
        Fl_Group {} {
          xywh {200 31 189 496} labelsize 12
          code0 {o->box(FL_NO_BOX);}
          code1 {//
            for (int i = 32; i < 64; ++i)
            {
                rs[i] = new RootSlot (0, 0, o->w(), 15, " ");
                rs[i]->init(i, &what, &slot, &RootProcess_::rootprocess,
                            (RootProcess_ *)this, bank, &rselected);

          }}
        } {}
        Fl_Group {} {
          xywh {390 30 189 496} labelsize 12 labelcolor 64
          code0 {o->box(FL_NO_BOX);}
          code1 {//
            for (int i = 64; i < 96; ++i)
            {
                rs[i] = new RootSlot (0, 0, o->w(), 15, " ");
                rs[i]->init(i, &what, &slot, &RootProcess_::rootprocess,
                            (RootProcess_ *)this, bank, &rselected);

          }}
        } {}
        Fl_Group {} {
          xywh {580 30 196 496} labelsize 12
          code0 {o->box(FL_NO_BOX);}
          code1 {//
            for (int i = 96; i < 128; ++i)
            {
                rs[i] = new RootSlot (0, 0, o->w(), 15, " ");
                rs[i]->init(i, &what, &slot, &RootProcess_::rootprocess,
                            (RootProcess_ *)this, bank, &rselected);

          }}
        } {}
      }
      Fl_Group rootmodeselect {
        xywh {5 528 635 42} box GTK_THIN_UP_BOX labelsize 12
      } {
        Fl_Box rootSelectPatch {
          xywh {11 555 83 9} box RFLAT_BOX color 103 labelcolor 49
        }
        Fl_Button rootreadbutton {
          label SELECT
          callback {//
          setRootHighlight(1);
          removeRootselection();}
          xywh {10 534 85 25} box PLASTIC_UP_BOX down_box PLASTIC_UP_BOX color 228 labelfont 9 labelsize 12 labelcolor 64
        }
        Fl_Box rootRenamePatch {
          xywh {100 555 83 9} box RFLAT_BOX color 208 labelcolor 49
        }
        Fl_Button rootrenamebutton {
          label RENAME
          callback {//
          setRootHighlight(5);
          removeRootselection();}
          xywh {100 534 85 25} box PLASTIC_UP_BOX down_box PLASTIC_UP_BOX color 228 labelfont 9 labelsize 12 labelcolor 64
        }
        Fl_Box rootSavePatch {
          xywh {190 555 83 9} box RFLAT_BOX color 173 labelcolor 49
        }
        Fl_Button rootwritebutton {
          label ADD
          callback {//
          setRootHighlight(2);
          removeRootselection();}
          xywh {190 534 85 25} box PLASTIC_UP_BOX down_box PLASTIC_UP_BOX color 228 labelfont 9 labelsize 12 labelcolor 64
        }
        Fl_Box rootDeletPatch {
          xywh {280 555 83 9} box RFLAT_BOX color 88 labelcolor 49
        }
        Fl_Button rootclearbutton {
          label DELETE
          callback {//
          setRootHighlight(3);
          removeRootselection();}
          xywh {280 534 85 25} box PLASTIC_UP_BOX down_box PLASTIC_UP_BOX color 228 labelfont 9 labelsize 12 labelcolor 64
        }
        Fl_Box rootSwapPatch {
          xywh {370 555 83 9} box RFLAT_BOX color 176 labelcolor 49
        }
        Fl_Button rootswapbutton {
          label SWAP
          callback {//
          setRootHighlight(4);
          removeRootselection();}
          xywh {370 534 85 24} box PLASTIC_UP_BOX down_box PLASTIC_UP_BOX color 228 labelfont 9 labelsize 12 labelcolor 64
        }
        Fl_Box rootImportPatch {
          xywh {460 555 83 9} box RFLAT_BOX color 93 labelcolor 49
        }
        Fl_Button rootimportbutton {
          label IMPORT
          callback {//
          setRootHighlight(6);
          removeRootselection();}
          xywh {460 533 85 25} box PLASTIC_UP_BOX down_box PLASTIC_UP_BOX color 228 labelfont 9 labelsize 12 labelcolor 64
        }
        Fl_Box rootExportPatch {
          xywh {550 555 83 9} box RFLAT_BOX color 78 labelcolor 49
        }
        Fl_Button rootexportbutton {
          label EXPORT
          callback {//
          setRootHighlight(7);
          removeRootselection();}
          xywh {550 533 85 25} box PLASTIC_UP_BOX down_box PLASTIC_UP_BOX color 228 labelfont 9 labelsize 12 labelcolor 64
        }
      }
      Fl_Button bankClose {
        label Close
        callback {//
            Hide(1);
            if (Fl::event_button() == 3)
            {
                if (bankFrom == 1)
                {
                    rootFrom = 2;
                    ShowRoot();
                }
                else if (bankFrom == 3)
                {
                    instFrom = 2;
                    ShowInst();
                }
            }
            else
                bankFrom = 0;}
        tooltip {Right click: also reopen previous} xywh {672 538 70 24} box THIN_UP_BOX color 196 labelsize 12 labelcolor 64
      }
    }
    Fl_Window rootuiwindow {
      label {Bank Root Paths}
      callback {Hide(2);}
      xywh {88 54 460 270} type Double labelsize 12 hide resizable
      code0 {readbankcfg();}
      code1 {o->copy_label(textMsgBuffer.fetch(collect_readData(synth, textMsgBuffer.push("Bank Root Paths"), UNUSED, TOPLEVEL::windowTitle)).c_str());}
      code2 {rootDW = o->w(); rootDH = o->h();}
      code3 {o->size_range(rootDW, rootDH, 0,0,0,0,1);}
    } {
      Fl_Browser rootsbrowse {
        callback {int tmp = o->value();
        activatebutton_rootdir(tmp!=0);
        if (tmp)
        {
            selectedRootID = reinterpret_cast<long>(o->data(tmp));
        }

        changeIDbutton->value(recoverID());
        oldrootID = changeIDbutton->value();
        Pend->hide();}
        xywh {10 10 445 200} type Hold labelsize 12 labelcolor 64 textsize 12 textcolor 64
      }
      Fl_Button addrootdirbutton {
        label {Add root directory...}
        callback {//
        // using 'false' here as we want to test for it
        // rather than automatically create it.
        string dirname = setfiler(synth,"Path to Bank Root dirs", "", false, TOPLEVEL::XML::Dir);
        if (dirname.length() < 3)
            return;
        int newdef = UNUSED;
        if (!collect_readData(synth, 0, BANK::isOccupiedRoot, TOPLEVEL::section::bank, 255, 255, 255, 255, 255, textMsgBuffer.push(dirname)))
        {
            if (choice(synth, "", "Yes", "No", "Directory is missing, or doesn't have at least \\n one bank with at least one instrument. \\nCreate missing entries?") != 2)
                return;
            newdef = 0;
        }
        send_data(TOPLEVEL::action::lowPrio | TOPLEVEL::action::forceUpdate, BANK::control::addNamedRoot, 0, TOPLEVEL::type::Write, TOPLEVEL::section::bank, newdef, UNUSED, UNUSED, UNUSED, textMsgBuffer.push(dirname));
        Pend->hide();}
        xywh {10 225 75 35} box GTK_THIN_UP_BOX color 198 labelsize 12 labelcolor 64 align 128
      }
      Fl_Button removerootdirbutton {
        label {Remove root dir...}
        callback {//
        if (selectedRootID >= 0)
        {
            synth->bank.removeRoot(selectedRootID);
            synth->saveBanks();
            readbankcfg();
        }
        activatebutton_rootdir(false);
        rescan_for_banks();
        Pend->hide();}
        xywh {94 225 75 35} box PLASTIC_UP_BOX color 228 labelsize 12 labelcolor 64 align 128 deactivate
        code0 {o->deactivate();}
      }
      Fl_Button makedefaultrootdirbutton {
        label {Make current}
        callback {//
        if (selectedRootID >= 0)
        {
            send_data(TOPLEVEL::action::lowPrio | TOPLEVEL::action::forceUpdate, BANK::control::selectRoot, selectedRootID, TOPLEVEL::type::Integer, TOPLEVEL::section::bank);

            banklist->value(0);
        }
        activatebutton_rootdir(false);
        Pend->hide();}
        xywh {178 225 75 35} box PLASTIC_UP_BOX color 228 labelsize 12 labelcolor 64 align 128 deactivate
        code0 {o->deactivate();}
      }
      Fl_Button showdefaultrootdirbutton {
        label {Open current}
        callback {//
        Showbank();
        if (Fl::event_button() == 3)
        {
            bankFrom = 1;
            Hide(2);
        }
        else
            rootFrom = 0;}
        tooltip {Right click: also close this} xywh {262 225 75 35} box GTK_THIN_UP_BOX color 198 labelsize 12 labelcolor 64 align 128
      }
      Fl_Spinner changeIDbutton {
        label {New ID}
        callback {Pend->show();}
        xywh {344 240 45 19} selection_color 64 labelsize 12 labelcolor 64 align 5 minimum 0 maximum 126 textsize 12 textcolor 64 deactivate
        code0 {oldrootID = o->value();}
        class WidgetSpinner
      }
      Fl_Button Pend {
        label Pending
        callback {//
        int tmp = changeIDbutton->value();
        if (tmp == oldrootID)
        {
            o->hide();
            return;
        }
        if (selectedRootID >= 0)
        {
            send_data(TOPLEVEL::action::lowPrio | TOPLEVEL::action::forceUpdate, BANK::control::changeRootId, tmp, TOPLEVEL::type::Integer, TOPLEVEL::section::bank, UNUSED, selectedRootID);
        }
        oldrootID = tmp;
        activatebutton_rootdir(false);
        o->hide();}
        tooltip {Click to set} xywh {340 220 56 18} box PLASTIC_UP_BOX color 90 labelsize 10 labelcolor 64 hide
      }
      Fl_Button rootClose {
        label Close
        callback {//
        if (Fl::event_button() == 3)
        {
            if (rootFrom == 2)
            Showbank();
        }
        else
            rootFrom = 0;
        Hide(2);}
        tooltip {Right click: also reopen previous} xywh {402 225 51 35} box THIN_UP_BOX color 196 labelsize 12 labelcolor 64
      }
    }
  }
  Function {setHighlight(int button)} {} {
    code {//
        mode = button;
        selectPatch->hide();
        renamePatch->hide();
        savePatch->hide();
        deletPatch->hide();
        swapPatch->hide();
        switch(button)
        {
            case 1:
                selectPatch->show();
            break;
            case 5:
                renamePatch->show();
            break;
            case 2:
                savePatch->show();
            break;
            case 3:
                deletPatch->show();
            break;
            case 4:
                swapPatch->show();
            break;
        }} {}
  }
  Function {setRootHighlight(int button)} {} {
    code {//
        r_mode = button;
        rootSelectPatch->hide();
        rootRenamePatch->hide();
        rootSavePatch->hide();
        rootDeletPatch->hide();
        rootSwapPatch->hide();
        rootImportPatch->hide();
        rootExportPatch->hide();
        switch(button)
        {
            case 1:
                rootSelectPatch->show();
            break;
            case 5:
                rootRenamePatch->show();
            break;
            case 2:
                rootSavePatch->show();
            break;
            case 3:
                rootDeletPatch->show();
            break;
            case 4:
                rootSwapPatch->show();
            break;
            case 6:
                rootImportPatch->show();
            break;
            case 7:
                rootExportPatch->show();
            break;
        }} {}
  }
  Function {fillSearchChoice()} {} {
    code {//

        int i = 0;
        string entry = type_list[i];
        while (entry != "@end")
        {
            searchType->add(entry.c_str());
            ++ i;
            entry = type_list[i];
        }} {}
  }
  Function {fillBrowser(int group)} {} {
    code {//
          string line;
          do
          {
              line = textMsgBuffer.fetch(fetchData(0, BANK::control::findInstrumentName, TOPLEVEL::section::bank, UNUSED, UNUSED, UNUSED, group));
              if (line !="@end")
                  searchbrowse->add(line.c_str());
          } while (line != "@end");} {}
  }
  Function {send_data(int action, int control, float value, int type, int part = UNUSED, int kititem = UNUSED, int engine = UNUSED, int insert = UNUSED, int parameter = UNUSED, int miscmsg = UNUSED)} {} {
    code {//
        type |= TOPLEVEL::type::Write;
        collect_writeData(synth, value, action, type, control, part, kititem, engine, insert, parameter, UNUSED, miscmsg);} {}
  }
  Function {fetchData(float value, int control, int part, int kititem = UNUSED, int engine = UNUSED, int insert = UNUSED, int parameter = UNUSED, int offset = UNUSED, int miscmsg = UNUSED, int request = UNUSED)} {return_type float
  } {
    code {//
        return collect_readData(synth, value, control, part, kititem, engine, insert, parameter, offset, miscmsg, request);} {}
  }
  Function {returns_update(CommandBlock *getData)} {} {
    code {//
    //int value_int = getData->data.value;
    unsigned char control = getData->data.control;
    unsigned char kititem = getData->data.kit;
    //unsigned char engine= getData->data.engine;
    unsigned char insert = getData->data.insert;

    int source = getData->data.source & TOPLEVEL::action::noAction;
    string message = textMsgBuffer.fetch(getData->data.miscmsg);
    switch(control)
    {
        case BANK::control::exportBank:
            if (source == TOPLEVEL::action::fromGUI)
                alert(synth, message);
            break;
        case BANK::control::renameInstrument:
            if (message.find("FAILED") != string::npos)
            {
                if (source == TOPLEVEL::action::fromGUI)
                    alert(synth, message);
            }
            else
                bs[insert]->copy_label(message.c_str());
            break;
        case BANK::control::saveInstrument:
            if (message.find("FAILED") != string::npos)
            {
                if (source == TOPLEVEL::action::fromGUI)
                    alert(synth, message);
            }
            else
                refreshinstrumentwindow();
            break;
        case BANK::control::deleteInstrument:
            if (message.find("FAILED") != string::npos)
            {
                if (source == TOPLEVEL::action::fromGUI)
                    alert(synth, message);
            }
            else
                rescan_for_banks();
            break;
        case BANK::control::selectFirstInstrumentToSwap:
            break;
        case BANK::control::selectSecondInstrumentAndSwap:

            if (message.find("FAILED") != string::npos)
                if (source == TOPLEVEL::action::fromGUI)
                    alert(synth, message);
            rescan_for_banks();
            break;

        case BANK::control::selectBank:
            rescan_for_banks();
            break;
        case BANK::control::renameBank:
        if (message.find("FAILED") != string::npos)
                if (source == TOPLEVEL::action::fromGUI)
                    alert(synth, message);
            rescan_for_banks();
            break;
        case BANK::control::createBank:
            if (message.find("FAILED") != string::npos)
                if (source == TOPLEVEL::action::fromGUI)
                    alert(synth, message);
            readbankcfg();
            rescan_for_banks();
            break;

        case BANK::control::selectFirstBankToSwap:
            break;
        case BANK::control::selectSecondBankAndSwap:
            if (message.find("FAILED") != string::npos)
                if (source == TOPLEVEL::action::fromGUI)
                    alert(synth, message);
            rescan_for_banks();
            break;

        case BANK::control::selectRoot:
            readbankcfg();
            rescan_for_banks();
            break;
        case BANK::control::changeRootId:
            readbankcfg();
            rescan_for_banks();
            break;
        case BANK::control::addNamedRoot:
            readbankcfg();
            rescan_for_banks();
            if (kititem != UNUSED)
                synth->getGuiMaster()->updatepart();
            break;
        case BANK::control::deselectRoot:
            readbankcfg();
            rescan_for_banks();
            break;
        case BANK::control::refreshDefaults:
            readbankcfg();
            break;
    }} {}
  }
  Function {BankUI(SynthEngine *_synth)} {} {
    code {//
    synth = _synth;
    fnr = &RootProcess_::rootprocess;
    root = & synth->bank;
    fnc = &BankProcess_::process;
    bank = & synth->bank;
    what = 0;
    nselected = -1;
    rselected = -1;
    instrumentSeen = false;
    bankSeen = false;
    rootSeen = false;
    searchSeen = false;
    make_window();
    r_mode = 1;
    mode = 1;
    bankS = 0;
    rootFrom = 0;
    bankFrom = 0;
    instFrom = 0;
    setHighlight(mode);
    setRootHighlight(r_mode);} {}
  }
  Function {~BankUI()} {return_type virtual
  } {
    code {//
        if (instrumentSeen)
            saveWin(synth, instrumentuiwindow->w(), instrumentuiwindow->h(), instrumentuiwindow->x(), instrumentuiwindow->y(), true, "Bank-instrument");
        instrumentuiwindow->hide();
        delete instrumentuiwindow;
        if (bankSeen)
            saveWin(synth, bankuiwindow->w(), bankuiwindow->h(), bankuiwindow->x(),  bankuiwindow->y(), true, "Bank-bank");
        bankuiwindow->hide();
        delete bankuiwindow;
        if (rootSeen)
            saveWin(synth,rootuiwindow->w(), rootuiwindow->h(),  rootuiwindow->x(),  rootuiwindow->y(), true, "Bank-root");
        rootuiwindow->hide();
        if (searchSeen)
            saveWin(synth,searchwin->w(), searchwin->h(),  searchwin->x(),  searchwin->y(), true, "Bank-search");
        searchwin->hide();
        delete searchwin;

        delete rootuiwindow;} {}
  }
  Function {Show()} {} {
    code {// called from part UI
    rescan_for_banks();
    set_bank_slot();
    ShowInst();
    mode = 1;
    removeselection();
    setHighlight(mode);
    refreshmainwindow();} {}
  }
  Function {ShowInst()} {} {
    code {//

    int X, Y, W, H, O;
    loadWin(synth, W, H, X, Y, O, "Bank-instrument");
    if (W < instDW || H < instDH)
    {
        W = instDW;
        H = instDH;
    }
    checkSane(X, Y, W, H, instDW, instDH);

    instrumentuiwindow->resize(X, Y, W, H);
    lastinstrumentW = 0;
    instrumentuiwindow->show();
    instrumentSeen = true;} {}
  }
  Function {Showbank()} {} {
    code {//

    int X, Y, W, H, O;
    loadWin(synth, W, H, X, Y, O, "Bank-bank");
    if (W < bankDW || H < bankDH)
    {
        W = bankDW;
        H = bankDH;
    }
    checkSane(X, Y, W, H, bankDW, bankDH);

    bankuiwindow->resize(X, Y, W, H);
    lastbankW = 0;
    bankuiwindow->show();
    bankSeen = true;} {}
  }
  Function {ShowRoot()} {} {
    code {//

    int X, Y, W, H, O;
    loadWin(synth, W, H, X, Y, O, "Bank-root");
    if (W < rootDW || H < rootDH)
    {
        W = rootDW;
        H = rootDH;
    }
    checkSane(X, Y, W, H, rootDW, rootDH);

    rootuiwindow->resize(X, Y, W, H);
    lastrootW = 0;
    rootuiwindow->show();
    rootSeen = true;} {}
  }
  Function {ShowSearch()} {} {
    code {//

    int X, Y, W, H, O;
    loadWin(synth, W, H, X, Y, O, "Bank-search");
    if (W < searchDW || H < searchDH)
    {
        W = searchDW;
        H = searchDH;
    }
    checkSane(X, Y, W, H, searchDW, searchDH);

    searchwin->resize(X, Y, W, H);
    if (unsearched)
    {
        fillBrowser(1);
        unsearched = false;
    }
    lastsearchW = 0;
    searchwin->show();
    searchSeen = true;} {}
  }
  Function {Hide(int type = 0)} {} {
    code {// also called from master UI
    switch (type)
    {
        case 0:
            saveWin(synth,instrumentuiwindow->w(), instrumentuiwindow->h(), instrumentuiwindow->x(), instrumentuiwindow->y(), false, "Bank-instrument");
            instrumentuiwindow->hide();
            lastinstrumentW = 0;
            instrumentSeen = false;
            break;
        case 1:
            saveWin(synth, bankuiwindow->w(), bankuiwindow->h(), bankuiwindow->x(),  bankuiwindow->y(), false, "Bank-bank");
            bankuiwindow->hide();
            lastbankW = 0;
            bankSeen = false;
            break;
        case 2:
            saveWin(synth,rootuiwindow->w(), rootuiwindow->h(),  rootuiwindow->x(),  rootuiwindow->y(), false, "Bank-root");
            rootuiwindow->hide();
            lastrootW = 0;
            rootSeen = false;
            break;
        case 3:
            saveWin(synth,searchwin->w(), searchwin->h(),  searchwin->x(),  searchwin->y(), false, "Bank-search");
            searchwin->hide();
            lastsearchW = 0;
            searchSeen = false;
            break;
        default:
            break;
    }} {}
  }
  Function {init(Fl_Spinner *cbwig_)} {} {
    code {//
    cbwig = cbwig_;
    rescan_for_banks();
    unsearched = true;
    searchType->value(1);
    lastinstrumentW = 0;
    lastbankW = 0;
    lastrootW = 0;
    lastsearchW = 0;} {}
  }
  Function {process()} {return_type void
  } {
    code {//
        int slot = this->slot;
        int curPart = collect_readData(synth, 0, MAIN::control::partNumber, TOPLEVEL::main); // make sure it's the right one!
        string thisname =  textMsgBuffer.fetch(fetchData(0, BANK::control::readInstrumentName, TOPLEVEL::section::bank, UNUSED, UNUSED, UNUSED, slot));
        bool slotFilled = (thisname > "!");
        if ((what == 1 || what == 3) && mode == 1 && slotFilled)
        {
            send_data(TOPLEVEL::action::forceUpdate, MAIN::control::loadInstrumentFromBank, slot, TOPLEVEL::type::Integer, TOPLEVEL::section::main, synth->getGuiMaster()->npart);
            // Reads from slot
            if (synth->getGuiMaster()->virkeyboard->virkeyboardwindow->visible())
                synth->getGuiMaster()->virkeyboard->virkeys->take_focus();
            if (what == 3)
                Hide(0);
            return;
        }

        if (mode == 5)
        {   // Rename slot
            if (slotFilled)
            {
                string newname = input_text(synth, "Instrument name:", thisname);
                if (newname == DEFAULT_NAME)
                    alert(synth, "Can't use name of default sound");
                else if (newname != thisname)
                    send_data(TOPLEVEL::action::lowPrio | TOPLEVEL::action::forceUpdate, BANK::control::renameInstrument, 0, TOPLEVEL::type::Integer, TOPLEVEL::section::bank, UNUSED, UNUSED, slot, UNUSED, synth->textMsgBuffer.push(newname));
            }
            mode = 1;
        }

        if (mode == 2)
        {   // save(write) to slot (choices reversed for 'No' priority)
            bool doit = true;
            if (synth->part[curPart]->Pname == DEFAULT_NAME)
            {
                alert(synth, "Can't store instrument with default name");
                mode = 1;
                doit = false;
            }
            else if (synth->part[curPart]->info.Ptype == 0)
            {
                if (choice(synth, "", "Save", "Cancel", "Please set instrument type before saving.\\nCopyright info also recommended.") != 2)
                    doit = false;
            }
            else if (slotFilled)
            {
                if (choice(synth, "", "Yes", "No", "Overwrite the slot no." + to_string(slot + 1) + "?") < 2)
                {
                    mode = 1;
                    doit = false;
                }
            }
            if (doit)
            {
                send_data(TOPLEVEL::action::lowPrio | TOPLEVEL::action::forceUpdate, BANK::control::saveInstrument, 0, TOPLEVEL::type::Integer, TOPLEVEL::section::bank, UNUSED, UNUSED, slot);
                mode = 1;
            }
        }

        if (mode == 3)
        {   // Clears the slot (choices reversed for 'No' priority)
            if (slotFilled)
            {
                if (choice(synth, "", "Yes", "No", "Clear the slot no. " + to_string(slot + 1) + "?") > 1)
                    send_data(TOPLEVEL::action::lowPrio | TOPLEVEL::action::forceUpdate, BANK::control::deleteInstrument, slot, TOPLEVEL::type::Write, TOPLEVEL::section::bank);
            }
            mode = 1;
        }

        if (mode == 4)
        {   // swap
            bool done = false;
            if (what == 1 && nselected >= 0)
            {
                send_data(TOPLEVEL::action::lowPrio | TOPLEVEL::action::forceUpdate, BANK::control::selectSecondInstrumentAndSwap, 0, TOPLEVEL::type::Integer, TOPLEVEL::section::bank, UNUSED, UNUSED, slot);
                nselected = -1;
                mode = 1;
                done = true;
            }
            if ((nselected < 0 || what == 2) && !done)
            {
                send_data(TOPLEVEL::action::lowPrio, BANK::control::selectFirstInstrumentToSwap, 0, TOPLEVEL::type::Integer, TOPLEVEL::section::bank, UNUSED, UNUSED, slot);
                nselected = slot;
            }
        }
        setHighlight(mode);
        if (mode != 4)
            refreshinstrumentwindow();} {}
  }
  Function {rootprocess()} {return_type void
  } {
    code {//
    unsigned int slot = this->slot;
    int rt = fetchData(0, BANK::control::selectRoot, TOPLEVEL::section::bank);
    int bt = fetchData(0, BANK::control::selectBank, TOPLEVEL::section::bank);
    string thisname = bank->getBankName(slot, rt);

    if ((what == 1 || what == 3) && r_mode == 1 && !thisname.empty())
    {
        // Selects from slot
        send_data(TOPLEVEL::action::lowPrio | TOPLEVEL::action::forceUpdate, BANK::control::selectBank, slot, TOPLEVEL::type::Integer, TOPLEVEL::section::bank);

        instFrom = 2;
        if (what == 3)
            Hide(1);

        cbwig->do_callback(); // what does this do?

        ShowInst();
        set_bank_slot(); // needed by 'old' menu selector
        refreshinstrumentwindow();
        return;
    }

    if (r_mode == 7)
    {
        string dirname = setfiler(synth,"Path for Bank Export", thisname, true, TOPLEVEL::XML::Bank);
        if (dirname.length() > 2)
            send_data(TOPLEVEL::action::lowPrio | TOPLEVEL::action::forceUpdate, MAIN::control::exportBank, slot, TOPLEVEL::type::Integer, TOPLEVEL::section::main, UNUSED, UNUSED, UNUSED, UNUSED, textMsgBuffer.push(string(dirname)));
        r_mode = 1;
    }

    if (r_mode == 6)
    {
        string dirname = setfiler(synth,"Bank to Import", "", false, TOPLEVEL::XML::Bank);
        if (dirname.length() > 2)
            send_data(TOPLEVEL::action::lowPrio | TOPLEVEL::action::forceUpdate, MAIN::control::importBank, slot, TOPLEVEL::type::Integer, TOPLEVEL::section::main, UNUSED, UNUSED, UNUSED, UNUSED, textMsgBuffer.push(string(dirname)));
        r_mode = 1;
    }

    if (r_mode == 5 && !thisname.empty())
    {   // Rename bank
        string tmp = input_text(synth, "Bank name:", thisname);
        if (tmp != thisname)
                send_data(TOPLEVEL::action::lowPrio | TOPLEVEL::action::forceUpdate, BANK::control::renameBank, slot, TOPLEVEL::type::Integer, TOPLEVEL::section::bank, UNUSED, UNUSED, UNUSED, UNUSED, textMsgBuffer.push(tmp));
        r_mode = 1;
    }

    if (r_mode == 2)
    {   // Create new bank and save to file
        if (!thisname.empty())
        {
            r_mode = 1;
            alert(synth, "Bank " + to_string(slot) + " already in use for " + thisname);
            return;
        }
        string dirname;
        dirname = input_text(synth, "New empty Bank:", "");
        if (!dirname.empty())
            send_data(TOPLEVEL::action::lowPrio | TOPLEVEL::action::forceUpdate, BANK::control::createBank, slot, TOPLEVEL::type::Integer | TOPLEVEL::type::Write, TOPLEVEL::section::bank, slot, UNUSED, UNUSED, UNUSED, textMsgBuffer.push(dirname));
        r_mode = 1;
        refreshmainwindow();
    }

    if (r_mode == 3)
    {
        if(!thisname.empty())
        {
            if (choice(synth, "", "Yes", "No", "Completely clear " + thisname + "?") > 1)
            {
                int clearit = true;
                int count = bank->getBankSize(slot, rt);
                if (count > 1)
                    clearit = choice(synth, "Yes", "", "STOP!", "There are " + to_string(count) + " instruments in this bank\\nThey will be permanently deleted") == 3;
                if (clearit)
                {
                    send_data(TOPLEVEL::action::lowPrio | TOPLEVEL::action::forceUpdate, MAIN::control::deleteBank, slot, TOPLEVEL::type::Integer, TOPLEVEL::section::main);
                }
            }
        }
        refreshmainwindow();
        r_mode = 1;
    }

    if (r_mode == 4)
    {   // Swap banks

            bool done = false;
            if (what == 1 && rselected >= 0)
            {
                send_data(TOPLEVEL::action::lowPrio | TOPLEVEL::action::forceUpdate, BANK::control::selectSecondBankAndSwap, 0, TOPLEVEL::type::Integer, TOPLEVEL::section::bank, slot);
                rselected = -1;
                rescan_for_banks();
                r_mode = 1;
                done = true;
            }
            if ((rselected < 0 || what == 2) && !done)
            {
                send_data(TOPLEVEL::action::lowPrio, BANK::control::selectFirstBankToSwap, 0, TOPLEVEL::type::Integer, TOPLEVEL::section::bank, slot);
                rselected = slot;
                rs[slot]->rootrefresh(bt, rt);
            }
    }
    setRootHighlight(r_mode);} {}
  }
  Function {refreshmainwindow()} {} {
    code {//
    int bk = fetchData(0, BANK::control::selectBank, TOPLEVEL::section::bank);
    int rt = fetchData(0, BANK::control::selectRoot, TOPLEVEL::section::bank);
    int last = fetchData(0, BANK::control::lastSeenInBank, TOPLEVEL::section::bank);

    instrumentuiwindow->copy_label(bank->getBankFileTitle(rt, bk).c_str());

    bankuiwindow->copy_label(bank->getRootFileTitle(rt).c_str());

    for (int i = 0; i < MAX_INSTRUMENTS_IN_BANK; ++i)
        bs[i]->refresh(bk, rt, last);
    for (int i = 0; i < MAX_BANKS_IN_ROOT; ++i)
        rs[i]->rootrefresh(bk, rt);} {}
  }
  Function {refreshinstrumentwindow()} {} {
    code {//
    int bk = fetchData(0, BANK::control::selectBank, TOPLEVEL::section::bank);
    int rt = fetchData(0, BANK::control::selectRoot, TOPLEVEL::section::bank);
    int last = fetchData(0, BANK::control::lastSeenInBank, TOPLEVEL::section::bank);
    //std::cout << "here ins " << int(last >> 15) << "  bank " << int((last >> 8) & 0x7f) << "  root " << int(last & 0x7f) << std::endl;
    for (int i = 0; i < MAX_INSTRUMENTS_IN_BANK; ++i)
    {
        bs[i]->refresh(bk, rt, last);
    }} {}
  }
  Function {theme()} {} {
    code {//
          if (instrumentSeen)
          {
              if(instrumentuiwindow->visible())
              {
                  lastinstrumentW = 0;
                  instrumentRtext();
              }
          }
          if (searchSeen)
          {
              if(searchwin->visible())
              {
                  lastsearchW = 0;
                  searchRtext();
              }
          }
          if (bankSeen)
          {
              if(bankuiwindow->visible())
              {
                  lastbankW = 0;
                  bankRtext();
              }
          }
          if (rootSeen)
          {
              if(rootuiwindow->visible())
              {
                  lastrootW = 0;
                  rootRtext();
              }
          }
         ;} {}
  }
  Function {wincheck()} {} {
    code {//
    if (instrumentSeen)
        instrumentRtext();
    if (searchSeen)
        searchRtext();
    if (bankSeen)
        bankRtext();
    if (rootSeen)
        rootRtext();} {}
  }
  Function {instrumentRtext()} {} {
    code {//
    if (lastinstrumentW == instrumentuiwindow->w())
        return;
    lastinstrumentW = instrumentuiwindow->w();

    float dScale = instrumentuiwindow->w() / float(instDW);
    if (dScale < 0.2f)
        dScale = 0.2f;

    int size = int(12 * dScale);

    B_search->labelsize(size);
    insRoots->labelsize(size);
    insBanks->labelsize(size);
    insT1->labelsize(size);
    insT2->labelsize(size);
    writebutton->labelsize(size);
    readbutton->labelsize(size);
    clearbutton->labelsize(size);
    swapbutton->labelsize(size);
    renamebutton->labelsize(size);
    insT3->labelsize(size);
    addpatch->labelsize(size);
    subpatch->labelsize(size);
    padpatch->labelsize(size);

    insClose->labelsize(size);

    banklist->textsize(size);
    int lineX;
    int lineY;
    for (int i = 0; i < MAX_INSTRUMENTS_IN_BANK; ++i)
    {
        if (i < 32)
        {
            lineX = int(5 * dScale);
        }
        else if (i < 64)
        {
            lineX = int(160 * dScale);
        }
        else if (i < 96)
        {
            lineX = int(315 * dScale);
        }
        else if (i < 128)
        {
            lineX = int(470 * dScale);
        }
        else
        {
            lineX = int(625 * dScale);
        }
        lineY = int((((i & 31) * 15.4f) + 33) * dScale);
        bs[i]->resize(lineX,  lineY , int(152 * dScale), 15 * dScale);
        bs[i]->labelsize(int(13 * dScale));
    }

    instrumentuiwindow->redraw();} {}
  }
  Function {searchRtext()} {} {
    code {//
    if (lastsearchW == searchwin->w())
        return;
    lastsearchW = searchwin->w();

    float dScale = searchwin->w() / float(searchDW);
    if (dScale < 0.2f)
        dScale = 0.2f;

    int size = int(13 * dScale);

    searchT->labelsize(size);
    searchClose->labelsize(size);
    searchType->labelsize(size);
        searchType->textsize(size);
    searchbrowse->textsize(size);

    noEntries->labelsize(int(30 * dScale));

    searchwin->redraw();} {}
  }
  Function {bankRtext()} {} {
    code {//
    if (lastbankW == bankuiwindow->w())
        return;
    lastbankW = bankuiwindow->w();

    float dScale = bankuiwindow->w() / float(bankDW);
    if (dScale < 0.2f)
        dScale = 0.2f;

    int size = int(12 * dScale);

    bankroot->labelsize(size);
    bankinst->labelsize(size);
    bankcurrent->labelsize(size);
    rootwritebutton->labelsize(size);
    rootreadbutton->labelsize(size);
    rootclearbutton->labelsize(size);
    rootswapbutton->labelsize(size);
    rootrenamebutton->labelsize(size);
    rootimportbutton->labelsize(size);
    rootexportbutton->labelsize(size);

    bankClose->labelsize(size);
    int lineX;
    int lineY;
    for (int i = 0; i < MAX_BANKS_IN_ROOT; ++i)
    {
        if (i < 32)
        {
            lineX = int(6 * dScale);
        }
        else if (i < 64)
        {
            lineX = int(200 * dScale);
        }
        else if (i < 96)
        {
            lineX = int(393 * dScale);
        }
        else
        {
            lineX = int(586 * dScale);
        }

        lineY = int((((i & 31) * 15.4f) + 33) * dScale);
        rs[i]->resize(lineX,  lineY , int(188 * dScale), 15 * dScale);
        rs[i]->labelsize(int(13 * dScale) - 1);
    }

    bankuiwindow->redraw();} {}
  }
  Function {rootRtext()} {} {
    code {//
    if (lastrootW == rootuiwindow->w())
        return;
    lastrootW = rootuiwindow->w();

    float dScale = rootuiwindow->w() / float(rootDW);
    if (dScale < 0.2f)
        dScale = 0.2f;

    int size = int(12 * dScale);

    addrootdirbutton->labelsize(size);
    removerootdirbutton->labelsize(size);
    makedefaultrootdirbutton->labelsize(size);
    showdefaultrootdirbutton->labelsize(size);
    Pend->labelsize(int(10 * dScale));
    changeIDbutton->labelsize(size);
        changeIDbutton->textsize(size);
    changeIDbutton->redraw();

    rootClose->labelsize(size);
    rootsbrowse->textsize(size);

    rootuiwindow->redraw();} {}
  }
  Function {refreshbankslot(int ins, int bk, int rt, int last)} {} {
    code {//
        bs[ins]->refresh(bk, rt, last);} {}
  }
  Function {removeselection()} {} {
    code {//
        if (nselected >= 0)
        {
            int ns = nselected;
            nselected = -1;
            bs[ns]->refresh(fetchData(0, BANK::control::selectBank, TOPLEVEL::section::bank), fetchData(0, BANK::control::selectRoot, TOPLEVEL::section::bank), fetchData(0, BANK::control::lastSeenInBank, TOPLEVEL::section::bank));
        }} {}
  }
  Function {removeRootselection()} {} {
    code {//
        if (rselected >= 0)
        {
            int rsel = rselected;
            rselected = -1;
            rs[rsel]->rootrefresh(fetchData(0, BANK::control::selectBank, TOPLEVEL::section::bank), fetchData(0, BANK::control::selectRoot, TOPLEVEL::section::bank));
        }} {}
  }
  Function {rescan_for_banks()} {} {
    code {//
    banklist->clear();
    const BankEntryMap &banks = bank->getBanks(fetchData(0, BANK::control::selectRoot, TOPLEVEL::section::bank));
    BankEntryMap::const_iterator it;
    for (it = banks.begin(); it != banks.end(); ++it)
    {
        if (!it->second.dirname.empty())
        {
            int n = banklist->add((asString(it->first) + ". " + it->second.dirname).c_str(), (const char *)0, (Fl_Callback*)0, reinterpret_cast<void *>(it->first));
            if (it->first == fetchData(0, BANK::control::selectBank, TOPLEVEL::section::bank))
            {
                banklist->value(n); // ensure correct bank in list
            }
        }
    }
    refreshmainwindow();} {}
  }
  Function {set_bank_slot()} {} {
    code {//
    size_t curID = fetchData(0, BANK::control::selectBank, TOPLEVEL::section::bank);
    const Fl_Menu_Item *curItem = 0;
    for (int i = 0; i < banklist->size(); i++)
    {
        const Fl_Menu_Item *item = banklist->menu() + i;
        if (item->label())
        {
            if (curID == reinterpret_cast<size_t>(item->user_data()))
            {
                curItem = item;
            }
        }
    }
    if (curItem)
    {
        banklist->value(curItem);
    }
    else
    {
        banklist->value(0);
    }} {}
  }
  Function {activatebutton_rootdir(bool active)} {} {
    code {//
        if (active)
        {
            removerootdirbutton->activate();
            makedefaultrootdirbutton->activate();
            changeIDbutton->activate();
        }
        else
        {
            removerootdirbutton->deactivate();
            makedefaultrootdirbutton->deactivate();
            changeIDbutton->deactivate();
            Pend->hide();
        }} {}
  }
  Function {readbankcfg()} {} {
    code {//
    string tmp;
    rootsbrowse->clear();
    const RootEntryMap &roots = synth->bank.getRoots();
    RootEntryMap::const_iterator it;
    for (it = roots.begin(); it != roots.end(); ++it)
    {
        if (!it->second.path.empty())
        {
            tmp = asString(it->first) + ". " + it->second.path;
            if (it->first == fetchData(0, BANK::control::selectRoot, TOPLEVEL::section::bank))
            {
                tmp += " *";
            }
            rootsbrowse->add(tmp.c_str(), reinterpret_cast<void *>(static_cast<long>(it->first)));
        }
    }} {}
  }
  Function {recoverID()} {return_type int
  } {
    code {//
    if (selectedRootID >= 0)
    {
        return selectedRootID;
    }
    return 0;} {}
  }
  decl {BankSlot *bs[MAX_INSTRUMENTS_IN_BANK];} {private local
  }
  decl {RootSlot *rs[MAX_BANKS_IN_ROOT];} {private local
  }
  decl {int slot, what; // "what" = what button is pressed} {private local
  }
  decl {int mode, r_mode, nselected, rselected;} {private local
  }
  decl {void (BankProcess_::* fnc)(void);} {private local
  }
  decl {void (RootProcess_::* fnr)(void);} {private local
  }
  decl {Fl_Spinner *cbwig;} {public local
  }
  decl {SynthEngine *synth;} {private local
  }
  decl {int bankS;} {private local
  }
  decl {long selectedRootID;} {private local
  }
  decl {int oldrootID;} {private local
  }
  decl {string rootuiwindowlabel;} {private local
  }
  decl {int rootFrom;} {private local
  }
  decl {bool rootSeen;} {private local
  }
  decl {int rootDW;} {private local
  }
  decl {int lastrootW;} {private local
  }
  decl {int rootDH;} {private local
  }
  decl {int bankFrom;} {private local
  }
  decl {int lastbankW;} {private local
  }
  decl {int bankDW;} {private local
  }
  decl {int bankDH;} {private local
  }
  decl {bool bankSeen;} {private local
  }
  decl {int instFrom;} {private local
  }
  decl {int instDW;} {private local
  }
  decl {int instDH;} {private local
  }
  decl {int lastinstrumentW;} {private local
  }
  decl {bool instrumentSeen;} {private local
  }
  decl {bool unsearched;} {public local
  }
  decl {int searchDW;} {private local
  }
  decl {int searchDH;} {private local
  }
  decl {int lastsearchW;} {private local
  }
  decl {bool searchSeen;} {private local
  }
}
