//=========================================================
//  MusE
//  Linux Music Editor
//  $Id: rack.cpp,v 1.1.1.1 2003/10/29 10:05:23 wschweer Exp $
//
//  (C) Copyright 2000-2003 Werner Schweer (ws@seh.de)
//=========================================================

#include <qtooltip.h>
#include <qpalette.h>
#include <qpainter.h>
#include <qpopupmenu.h>

#include "rack.h"
#include "song.h"
#include "seq.h"
#include "audio.h"
#include "plugins/plugin.h"
#include "icons.h"

//---------------------------------------------------------
//   class RackSlot
//---------------------------------------------------------

class RackSlot : public QListBoxItem {
      AudioNode* node;
      int idx;

      virtual void paint(QPainter*);
      virtual int height(const QListBox*) const { return 18; }

   public:
      RackSlot(QListBox* lb, AudioNode* n, int);
      };

//---------------------------------------------------------
//   RackSlot
//---------------------------------------------------------

RackSlot::RackSlot(QListBox* b, AudioNode* n, int i)
   : QListBoxItem(b)
      {
      idx  = i;
      node = n;
      }

//---------------------------------------------------------
//   paint
//---------------------------------------------------------

void RackSlot::paint(QPainter* painter)
      {
      painter->save();
      if (node == 0 || !node->efxPipe()->isOn(idx)) {
            const QColorGroup& g = listBox()->colorGroup();
            painter->fillRect(0,0,listBox()->width(),height(listBox()), g.dark());
            painter->setPen(g.light());
            }
      QFontMetrics fm = painter->fontMetrics();
      QString s(node->efxPipe()->name(idx));
      painter->drawText(3, fm.ascent() + fm.leading()/2, s);
      painter->restore();
      }

//---------------------------------------------------------
//   EffectRack
//---------------------------------------------------------

EffectRack::EffectRack(QWidget* parent, AudioNode* as, int n)
   : QListBox(parent)
      {
      setFont(font1);
      src = as;
      channels = n;

      setHScrollBarMode(AlwaysOff);
      setVScrollBarMode(AlwaysOff);
      setSelectionMode(Single);
      for (int i = 0; i < PipelineDepth; ++i)
            new RackSlot(this, src, i);
      connect(this, SIGNAL(contextMenuRequested(QListBoxItem*, const QPoint&)),
         this, SLOT(menuRequested(QListBoxItem*, const QPoint&)));
      connect(this, SIGNAL(doubleClicked(QListBoxItem*)),
         this, SLOT(doubleClicked(QListBoxItem*)));
      connect(song, SIGNAL(songChanged(int)), SLOT(songChanged(int)));
      QToolTip::add(this, tr("effect rack"));
      }

//---------------------------------------------------------
//   songChanged
//---------------------------------------------------------

void EffectRack::songChanged(int typ)
      {
      if (typ & SC_ROUTE) {
            for (int i = 0; i < PipelineDepth; ++i)
                  updateItem(i);
            }
      }

//---------------------------------------------------------
//   minimumSizeHint
//---------------------------------------------------------

QSize EffectRack::minimumSizeHint() const
      {
      return QSize(10, 18 * PipelineDepth);
      }

//---------------------------------------------------------
//   menuRequested
//---------------------------------------------------------

void EffectRack::menuRequested(QListBoxItem* it, const QPoint& pt)
      {
      if (it == 0)
            return;
      RackSlot* curitem = (RackSlot*)it;
      int idx = index(curitem);
      QString name;
      bool mute;
      Pipeline* pipe = src->efxPipe();
      if (pipe) {
            name  = pipe->name(idx);
            mute  = pipe->isOn(idx);
            }

      enum { NEW, UP, DOWN, REMOVE, BYPASS, SHOW };
      QPopupMenu* menu = new QPopupMenu;
      menu->insertItem(QIconSet(*upIcon), tr("move up"),   UP, UP);
      menu->insertItem(QIconSet(*downIcon), tr("move down"), DOWN, DOWN);
      menu->insertItem(tr("remove"),    REMOVE, REMOVE);
      menu->insertItem(tr("bypass"),    BYPASS, BYPASS);
      menu->insertItem(tr("show gui"),  SHOW, SHOW);

      menu->setItemChecked(BYPASS, !pipe->isOn(idx));
      menu->setItemChecked(SHOW, pipe->guiVisible(idx));

      if (pipe->empty(idx)) {
            menu->insertItem(tr("new"), NEW, NEW);
            menu->setItemEnabled(UP, false);
            menu->setItemEnabled(DOWN, false);
            menu->setItemEnabled(REMOVE, false);
            menu->setItemEnabled(BYPASS, false);
            menu->setItemEnabled(SHOW, false);
            }
      else {
            menu->insertItem(tr("change"), NEW, NEW);
            if (idx == 0)
                  menu->setItemEnabled(UP, false);
            if (idx == (PipelineDepth-1))
                  menu->setItemEnabled(DOWN, false);
            }

      int sel = menu->exec(pt, 1);
      delete menu;
      if (sel == -1)
            return;

      switch(sel) {
            case NEW:
                  {
                  Plugin* plugin = PluginDialog::getPlugin(this);
                  if (plugin) {
                        PluginI* plugi = new PluginI();
                        if (plugi->initPluginInstance(plugin, channels)) {
                              printf("cannot intantiate plugin <%s>\n",
                                 plugin->name().latin1());
                              delete plugi;
                              break;
                              }
                        audio->msgAddPlugin(src, idx, plugi);
                        }
                  break;
                  }
            case REMOVE:
                  audio->msgAddPlugin(src, idx, 0);
                  break;
            case BYPASS:
                  {
                  bool flag = !pipe->isOn(idx);
                  pipe->setOn(idx, flag);
                  break;
                  }
            case SHOW:
                  {
                  bool flag = !pipe->guiVisible(idx);
                  pipe->showGui(idx, flag);
                  break;
                  }
            case UP:
                  if (idx > 0) {
                        setCurrentItem(idx-1);
                        pipe->move(idx, true);
                        }
                  break;
            case DOWN:
                  if (idx < (PipelineDepth-1)) {
                        setCurrentItem(idx+1);
                        pipe->move(idx, false);
                        }
                  break;
            }
      update();
      }

//---------------------------------------------------------
//   doubleClicked
//    toggle gui
//---------------------------------------------------------

void EffectRack::doubleClicked(QListBoxItem* it)
      {
      if (it == 0)
            return;
      RackSlot* item = (RackSlot*)it;
      int idx        = index(item);
      Pipeline* pipe = src->efxPipe();
      if (pipe) {
            bool flag = !pipe->guiVisible(idx);
            pipe->showGui(idx, flag);
            }
      }

