From 762f8a8a9c8c42ea4155ea222991ebe544d32b27 Mon Sep 17 00:00:00 2001
From: Werner Schweer <ws.seh.de>
Date: Fri, 1 Dec 2006 13:42:37 +0000
Subject: updates

---
 muse/muse/waveedit/waveedit.cpp |  35 ++-
 muse/muse/waveedit/waveedit.h   |   1 +
 muse/muse/waveedit/waveview.cpp | 467 ++++++++++++++++++++++++++++++++++------
 muse/muse/waveedit/waveview.h   |  38 +++-
 4 files changed, 467 insertions(+), 74 deletions(-)

diff --git a/muse/muse/waveedit/waveedit.cpp b/muse/muse/waveedit/waveedit.cpp
index 9a68b5cf..c54265a0 100644
--- a/muse/muse/waveedit/waveedit.cpp
+++ b/muse/muse/waveedit/waveedit.cpp
@@ -94,7 +94,10 @@ WaveEdit::WaveEdit(PartList* pl, bool init)
       tools->addAction(undoAction);
       tools->addAction(redoAction);
 
-      connect(muse, SIGNAL(configChanged()), SLOT(configChanged()));
+      const int waveeditTools = PointerTool | PencilTool 
+         | RubberTool | DrawTool;
+      EditToolBar* tools2 = new EditToolBar(this, waveeditTools);
+      addToolBar(tools2);
 
       //--------------------------------------------------
       //    Transport Bar
@@ -130,6 +133,7 @@ WaveEdit::WaveEdit(PartList* pl, bool init)
       view->setRaster(0);
       view->setFollow(INIT_FOLLOW);
 
+      connect(muse, SIGNAL(configChanged()), SLOT(configChanged()));
       connect(song, SIGNAL(posChanged(int,const AL::Pos&,bool)), view, SLOT(setLocatorPos(int,const AL::Pos&,bool)));
       view->setLocatorPos(0, song->cpos(), true);
       view->setLocatorPos(1, song->lpos(), false);
@@ -146,6 +150,9 @@ WaveEdit::WaveEdit(PartList* pl, bool init)
       p2 += AL::sigmap.ticksMeasure(p2.tick());  // show one more measure
       view->setTimeRange(p1, p2);
 
+      connect(view, SIGNAL(toolChanged(int)), tools2, SLOT(set(int)));
+      connect(tools2, SIGNAL(toolChanged(int)), view, SLOT(setTool(int)));
+
 //      view->selectFirst();
       configChanged();
       if (init)
@@ -233,6 +240,27 @@ void WaveEdit::keyPressEvent(QKeyEvent* event)
             }
       }
 
+//---------------------------------------------------------
+//   read
+//---------------------------------------------------------
+
+void WaveEdit::read(QDomNode node)
+      {
+      for (node = node.firstChild(); !node.isNull(); node = node.nextSibling()) {
+            QDomElement e = node.toElement();
+            QString tag(e.tagName());
+            if (tag == "CtrlEdit") {
+                  int id = e.attribute("id","0").toInt();
+                  int h = e.attribute("h","50").toInt();
+                  view->addController(id, h);
+                  }
+            else
+                  AL::readProperties(this, node);
+            }
+      view->layout1();
+      }
+
+
 //---------------------------------------------------------
 //   write
 //---------------------------------------------------------
@@ -250,6 +278,11 @@ void WaveEdit::write(Xml& xml) const
             }
       xml.stag(metaObject()->className());
       xml.writeProperties(this);
+      const CtrlEditList* el = view->getCtrlEditors();
+      for (ciCtrlEdit i = el->begin(); i != el->end(); ++i) {
+            xml.tagE("CtrlEdit h=\"%d\" id=\"%d\"",
+               (*i)->height(), (*i)->ctrl()->id());
+            }
       xml.etag(metaObject()->className());
       }
 
diff --git a/muse/muse/waveedit/waveedit.h b/muse/muse/waveedit/waveedit.h
index 85d9a726..f861587d 100644
--- a/muse/muse/waveedit/waveedit.h
+++ b/muse/muse/waveedit/waveedit.h
@@ -70,6 +70,7 @@ class WaveEdit : public Editor {
       WaveEdit(PartList*, bool);
       ~WaveEdit();
       PartList* parts() const { return _parts; }
+      void read(QDomNode node);
       void write(Xml& xml) const;
 
       enum { CMD_MUTE=0, CMD_NORMALIZE, CMD_FADE_IN, CMD_FADE_OUT, CMD_REVERSE,
diff --git a/muse/muse/waveedit/waveview.cpp b/muse/muse/waveedit/waveview.cpp
index 1164df87..6659274d 100644
--- a/muse/muse/waveedit/waveview.cpp
+++ b/muse/muse/waveedit/waveview.cpp
@@ -30,6 +30,8 @@
 #include "audio.h"
 #include "gconfig.h"
 #include "part.h"
+#include "widgets/simplebutton.h"
+#include "utils.h"
 
 static const int partLabelHeight = 13;
 
@@ -41,6 +43,8 @@ WaveView::WaveView(WaveEdit* pr)
    : TimeCanvas(TIME_CANVAS_WAVEEDIT)
       {
       setMarkerList(song->marker());
+      curSplitter    = -1;
+      dragSplitter   = false;
       selectionStart = 0;
       selectionStop  = 0;
       lastGainvalue  = 100;
@@ -221,98 +225,184 @@ void WaveView::songChanged(int flags)
       }
 
 //---------------------------------------------------------
-//   viewMousePressEvent
+//   mousePress
 //---------------------------------------------------------
 
-void WaveView::viewMousePressEvent(QMouseEvent* /*event*/)
+void WaveView::mousePress(QMouseEvent* me)
       {
-#if 0
-      button = event->button();
-      unsigned x = event->x();
-
-      switch (button) {
-            case Qt::LeftButton:
-                  if (mode == NORMAL) {
-                        // redraw and reset:
-                        if (selectionStart != selectionStop) {
-                              selectionStart = selectionStop = 0;
-                              update();
-                              }
-                        mode = DRAG;
-                        dragstartx = x;
-                        selectionStart = selectionStop = x;
-                        }
-                  break;
+      QPoint pos(me->pos());
 
-            case Qt::MidButton:
-            case Qt::RightButton:
-            default:
-                  break;
+      if (rCanvasA.contains(pos)) {
+//            mousePressCanvasA(me);
+            return;
+            }
+      if (curSplitter != -1) {
+            dragSplitter = true;
+            splitterY = pos.y();
+            return;
+            }
+
+      if (rCanvasB.contains(pos)) {
+            for (iCtrlEdit i = ctrlEditList.begin(); i != ctrlEditList.end(); ++i) {
+                  CtrlEdit* c = *i;
+                  QRect r(rCanvasB.x(), rCanvasB.y() + c->y + splitWidth,
+                     rCanvasB.width(), c->cheight());
+                  if (r.contains(pos)) {
+                        c->mousePress(pos - r.topLeft(), me->button(), me->modifiers());
+                        break;
+                        }
+                  }
             }
-      viewMouseMoveEvent(event);
-#endif
       }
 
 //---------------------------------------------------------
-//   viewMouseReleaseEvent
+//   mouseRelease
 //---------------------------------------------------------
 
-void WaveView::viewMouseReleaseEvent(QMouseEvent*)
+void WaveView::mouseRelease(QMouseEvent* me)
       {
-#if 0
-      button = Qt::NoButton;
-
-      if (mode == DRAG) {
-            mode = NORMAL;
-            //printf("selectionStart=%d selectionStop=%d\n", selectionStart, selectionStop);
+      if (dragSplitter) {
+            dragSplitter = false;
+            return;
+            }
+      QPoint pos(me->pos());
+      if (rCanvasA.contains(pos)) {
+            // mouseReleaseCanvasA(me);
+            return;
+            }
+      if (rCanvasB.contains(pos)) {
+            for (iCtrlEdit i = ctrlEditList.begin(); i != ctrlEditList.end(); ++i) {
+                  CtrlEdit* c = *i;
+                  QRect r(rCanvasB.x(), rCanvasB.y() + c->y + splitWidth,
+                     rCanvasB.width(), c->cheight());
+                  if (r.contains(pos)) {
+                        c->mouseRelease();
+                        break;
+                        }
+                  }
             }
-#endif
       }
 
 //---------------------------------------------------------
-//   viewMouseMoveEvent
+//   mouseMove
 //---------------------------------------------------------
 
-void WaveView::viewMouseMoveEvent(QMouseEvent* /*event*/)
+void WaveView::mouseMove(QPoint pos)
       {
-#if 0
-      unsigned x = event->x();
-      emit timeChanged(x);
-
-      int i;
-      switch (button) {
-            case Qt::LeftButton:
-                  i = 0;
-                  if (mode == DRAG) {
-                        if (x < dragstartx) {
-                              selectionStart = x;
-                              selectionStop = dragstartx;
-                              }
-                        else {
-                              selectionStart = dragstartx;
-                              selectionStop = x;
+      if (dragSplitter) {
+            int deltaY = pos.y() - splitterY;
+
+            iCtrlEdit i = ctrlEditList.begin();
+            int y = 0;
+            if (curSplitter > 0) {
+                  int k = 0;
+                  CtrlEdit* c = 0;
+                  for (; i != ctrlEditList.end(); ++i, ++k) {
+                        c = *i;
+                        y += c->height();
+                        if ((k+1) == curSplitter)
+                                    break;
+                        }
+                  if (i == ctrlEditList.end()) {
+                        printf("unexpected edit list end, curSplitter %d\n", curSplitter);
+                        return;
+                        }
+                  if (c->height() + deltaY < splitWidth)
+                        deltaY = splitWidth - c->height();
+                  ++i;
+                  int rest = 0;
+                  for (iCtrlEdit ii = i; ii != ctrlEditList.end(); ++ii)
+                        rest += (*ii)->cheight();
+                  if (rest < deltaY)
+                        deltaY = rest;
+                  c->setHeight(c->height() + deltaY);
+                  layoutPanelB(c);
+                  y += deltaY;
+                  }
+            //
+            //    layout rest, add deltaY vertical
+            //
+            int rest = 0;
+            for (iCtrlEdit ii = i; ii != ctrlEditList.end(); ++ii) {
+                  CtrlEdit* c = *ii;
+                  rest += c->cheight();
+                  }
+            if (rest < deltaY)
+                        deltaY = rest;
+            rest = deltaY;
+            for (; i != ctrlEditList.end(); ++i) {
+                  CtrlEdit* c = *i;
+                  int d = c->cheight();
+                  if (d > deltaY)
+                              d = deltaY;
+                  c->setHeight(c->height() - d);
+                  c->y = y;
+                  layoutPanelB(c);
+                  y += c->height();
+                  deltaY -= d;
+                  if (deltaY == 0)
+                              break;
+                  }
+            if (i != ctrlEditList.end())
+                  ++i;
+            for (; i != ctrlEditList.end(); ++i) {
+                  CtrlEdit* c = *i;
+                  c->y = y;
+                  y += c->height();
+                  }
+            if (curSplitter == 0)
+                        resizeController(ctrlHeight - rest);
+            else
+                        widget()->update(rPanelB | rCanvasB);
+            splitterY = pos.y();
+            updatePartControllerList();
+            return;
+            }
+      if (rCanvasA.contains(pos)) {
+            // mouseMoveCanvasA(pos - rCanvasA.topLeft());
+            return;
+            }
+      if (button == 0) {
+            if (rPanelB.contains(pos) || rCanvasB.contains(pos)) {
+                  int y = pos.y() - rPanelB.y();
+                  int k = 0;
+                  for (iCtrlEdit i = ctrlEditList.begin(); i != ctrlEditList.end(); ++i, ++k) {
+                        CtrlEdit* c = *i;
+                        if (y >= c->y && y < (c->y + splitWidth)) {
+                              curSplitter = k;
+                              setCursor();
+                              return;
                               }
+                        int ypos = y - c->y - splitWidth;
+                        if (ypos >= 0)
+                              emit yChanged(c->pixel2val(ypos));
                         }
-                  break;
-            case Qt::MidButton:
-                  i = 1;
-                  break;
-            case Qt::RightButton:
-                  i = 2;
-                  break;
-            default:
-                  return;
+                  }
+            if (curSplitter != -1) {
+                  curSplitter = -1;
+                  setCursor();
+                  }
+            return;
             }
-      Pos p(AL::tempomap.frame2tick(x), true);
-      song->setPos(i, p);
-#endif
+      if (rCanvasB.contains(pos)) {
+            for (iCtrlEdit i = ctrlEditList.begin(); i != ctrlEditList.end(); ++i) {
+                  CtrlEdit* c = *i;
+                  QRect r(rCanvasB.x(), rCanvasB.y() + c->y + splitWidth,
+                     rCanvasB.width(), c->cheight());
+                  if (r.contains(pos)) {
+                        c->mouseMove(pos - r.topLeft());
+                        break;
+                        }
+                  }
+            }
+
       }
 
 //---------------------------------------------------------
 //   cmd
 //---------------------------------------------------------
 
-void WaveView::cmd(const QString& c)
+void WaveView::cmd(const QString&)
       {
 #if 0
       int modifyoperation = -1;
@@ -786,3 +876,250 @@ void WaveView::range(AL::Pos& s, AL::Pos& e) const
       e.setFrame(endFrame);
       }
 
+//---------------------------------------------------------
+//   layout
+//---------------------------------------------------------
+
+void WaveView::layout()
+      {
+      int n = ctrlEditList.size();
+      if (n == 0)
+            return;
+      if (ctrlHeight == 0) {
+            int wh = widget()->height();
+            resizeController(wh < 120 ? wh / 2 : 100);
+            }
+      // check, if layout is ok already; this happens after
+      // song load
+      int h = 0;
+      for (iCtrlEdit i = ctrlEditList.begin(); i != ctrlEditList.end(); ++i) {
+            CtrlEdit* c = *i;
+            h += c->height();
+            }
+      if (h == ctrlHeight) {
+            for (iCtrlEdit i = ctrlEditList.begin(); i != ctrlEditList.end(); ++i)
+                  layoutPanelB(*i);
+            return;
+            }
+      int y = 0;
+      int sch = ctrlHeight / n;
+      for (iCtrlEdit i = ctrlEditList.begin(); i != ctrlEditList.end(); ++i) {
+            CtrlEdit* c = *i;
+            c->y = y;
+            c->setHeight(sch);
+            layoutPanelB(c);
+            y += sch;
+            }      
+      }
+
+//---------------------------------------------------------
+//   layout1
+//---------------------------------------------------------
+
+void WaveView::layout1()
+      {
+      int n = ctrlEditList.size();
+      if (n == 0)
+            return;
+      int y = 0;
+      for (iCtrlEdit i = ctrlEditList.begin(); i != ctrlEditList.end(); ++i) {
+            CtrlEdit* c = *i;
+            c->y = y;
+            y += c->height();
+            }
+      resizeController(y);      
+      }
+
+//---------------------------------------------------------
+//   layoutPanelB
+//---------------------------------------------------------
+
+void WaveView::layoutPanelB(CtrlEdit* c)
+      {
+      int y = c->y;
+      int h = c->height();
+      int bx = rPanelB.x() + rPanelB.width() - 23;
+      int by = rPanelB.y() + y + h - 19;
+      c->minus->setGeometry(bx, by, 18, 18);
+      bx = rPanelB.x() + 1;
+      by = rPanelB.y() + y + 5;
+      c->sel->setGeometry(bx, by, rPanelB.width() - 5, 18);
+      }
+
+//---------------------------------------------------------
+//   addController
+//---------------------------------------------------------
+
+void WaveView::addController()
+      {
+      int n = ctrlEditList.size();
+      CtrlEdit* ce = new CtrlEdit(widget(), this, curPart->track());
+      ce->setHeight(50);
+      ctrlEditList.push_back(ce);
+
+      ce->minus->defaultAction()->setData(n);
+      connect(ce->minus, SIGNAL(triggered(QAction*)), SLOT(removeController(QAction*)));
+      ce->minus->show();
+      ce->sel->show();
+
+      layout();
+      widget()->update();
+      updatePartControllerList();
+      }
+
+void WaveView::addController(int id, int h)
+      {
+      ctrlHeight += h;
+      int n = ctrlEditList.size();
+      
+      CtrlEdit* ce = new CtrlEdit(widget(), this, curPart->track());
+      ce->setHeight(h);
+      ce->setCtrl(id);
+      ctrlEditList.push_back(ce);
+
+      ce->minus->defaultAction()->setData(n);
+      connect(ce->minus, SIGNAL(triggered(QAction*)), SLOT(removeController(QAction*)));
+      }
+
+//---------------------------------------------------------
+//   removeController
+//---------------------------------------------------------
+
+void WaveView::removeController(QAction* a)
+      {
+      int id = a->data().toInt();
+
+      int k = 0;
+      for (iCtrlEdit i = ctrlEditList.begin(); i != ctrlEditList.end(); ++i, ++k) {
+            if (k == id) {
+                  CtrlEdit* c = *i;
+                  delete c;
+                  ctrlEditList.erase(i);
+                  break;
+                  }
+             }
+      k = 0;
+      for (iCtrlEdit i = ctrlEditList.begin(); i != ctrlEditList.end(); ++i, ++k) {
+            CtrlEdit* c = *i;
+            c->minus->defaultAction()->setData(k);
+            }
+
+      if (ctrlEditList.empty())
+            resizeController(0);
+      else
+            layout();
+      widget()->update();
+      updatePartControllerList();
+      }
+
+//---------------------------------------------------------
+//   updatePartControllerList
+//---------------------------------------------------------
+
+void WaveView::updatePartControllerList()
+      {
+      if (curPart == 0)
+            return;
+      CtrlCanvasList* cl = curPart->getCtrlCanvasList();
+      cl->clear();
+      for (iCtrlEdit i = ctrlEditList.begin(); i != ctrlEditList.end(); ++i) {
+            CtrlCanvas cc;
+            cc.ctrlId = (*i)->ctrlId;
+            cc.height = (*i)->height();
+            cl->push_back(cc);
+            }      
+      }
+
+//---------------------------------------------------------
+//   paintControllerCanvas
+//    r(0, 0) is PanelB topLeft()
+//---------------------------------------------------------
+
+void WaveView::paintControllerCanvas(QPainter& p, QRect r)
+      {
+      int x1 = r.x();
+      int x2 = x1 + r.width();
+
+      int xx2 = rCanvasB.width();
+      if (xx2 >= x2)
+                  x2 = xx2 - 2;
+      for (iCtrlEdit i = ctrlEditList.begin(); i != ctrlEditList.end(); ++i) {
+            CtrlEdit* c = *i;
+            int         y = c->y;
+            paintHLine(p, x1, x2, y);
+            p.setPen(lineColor[0]);
+            p.drawLine(xx2-1, 1, xx2-1, splitWidth-2);
+
+            QRect  rc(0, y + splitWidth, rCanvasB.width(), c->cheight());
+            QPoint pt(rc.topLeft());
+            rc &= r;
+            if (!rc.isEmpty()) {
+                  p.translate(pt);
+                  c->paint(p, rc.translated(-pt));
+                  p.translate(-pt);
+                  }
+            }
+      }
+
+//---------------------------------------------------------
+//   paintControllerPanel
+//    panelB
+//---------------------------------------------------------
+
+void WaveView::paintControllerPanel(QPainter& p, QRect r)
+      {
+      p.fillRect(r, QColor(0xe0, 0xe0, 0xe0));
+      int x1 = r.x();
+      int x2 = x1 + r.width();
+
+      paintVLine(p, r.y() + splitWidth, r.y() + r.height(),
+         rPanelB.x() + rPanelB.width());
+
+      if (x1 == 0)
+                  x1 = 1;
+      for (iCtrlEdit i = ctrlEditList.begin(); i != ctrlEditList.end(); ++i) {
+            CtrlEdit* c = *i;
+            paintHLine(p, x1, x2, c->y);
+            p.setPen(lineColor[0]);
+            p.drawLine(0, 1, 0, splitWidth-2);
+            }
+      }
+
+//---------------------------------------------------------
+//   setCursor
+//---------------------------------------------------------
+
+void WaveView::setCursor()
+      {
+      if (curSplitter != -1) {
+            widget()->setCursor(Qt::SplitVCursor);
+            return;
+            }
+      TimeCanvas::setCursor();
+      }
+
+//---------------------------------------------------------
+//   enterB
+//---------------------------------------------------------
+
+void WaveView::enterB()
+      {
+      if ((button == 0) && curSplitter != -1) {
+            curSplitter = -1;
+            setCursor();
+            }
+      }
+
+//---------------------------------------------------------
+//   leaveB
+//---------------------------------------------------------
+
+void WaveView::leaveB()
+      {
+      if ((button == 0) && (curSplitter != -1)) {
+            curSplitter = -1;
+            setCursor();
+            }
+      }
+
+
diff --git a/muse/muse/waveedit/waveview.h b/muse/muse/waveedit/waveview.h
index 617a8744..462ce26d 100644
--- a/muse/muse/waveedit/waveview.h
+++ b/muse/muse/waveedit/waveview.h
@@ -24,6 +24,7 @@
 #include "al/pos.h"
 #include "wave.h"
 #include "awl/tcanvas.h"
+#include "ctrl/ctrledit.h"
 
 class PartList;
 class QPainter;
@@ -50,7 +51,10 @@ typedef std::list<WaveEventSelection>::iterator iWaveSelection;
 //---------------------------------------------------------
 
 class WaveView : public TimeCanvas {
+      Q_OBJECT
+
       WaveEdit* editor;
+      CtrlEditList ctrlEditList;
 
       int startFrame;
       int endFrame;
@@ -61,16 +65,16 @@ class WaveView : public TimeCanvas {
       enum { MUTE = 0, NORMALIZE, FADE_IN, FADE_OUT, REVERSE, GAIN, EDIT_EXTERNAL }; //!< Modify operations
 
       unsigned selectionStart, selectionStop, dragstartx;
+      int curSplitter;  // -1 mouse not in splitter
+      bool dragSplitter;
+      int splitterY;
 
-      Q_OBJECT
       virtual void paint(QPainter&, QRect);
-
-//      virtual void pdraw(QPainter&, const QRect&);
-//      virtual void draw(QPainter&, const QRect&);
-
-      virtual void viewMousePressEvent(QMouseEvent*);
-      virtual void viewMouseMoveEvent(QMouseEvent*);
-      virtual void viewMouseReleaseEvent(QMouseEvent*);
+      virtual void mousePress(QMouseEvent*);
+      virtual void mouseMove(QPoint);
+      virtual void enterB();
+      virtual void leaveB();
+      virtual void mouseRelease(QMouseEvent*);
 
       bool getUniqueTmpfileName(QString& newFilename); //!< Generates unique filename for temporary SndFile
       WaveSelectionList getSelection(unsigned startpos, unsigned stoppos);
@@ -90,15 +94,33 @@ class WaveView : public TimeCanvas {
       //void applyLadspa(unsigned channels, float** data, unsigned length); //!< Apply LADSPA plugin on selection
 
       void drawWavePart(QPainter& p, Part* wp, int y0, int th, int from, int to);
+      virtual void addController();
+      virtual void layout();
+      void layoutPanelB(CtrlEdit*);
+      void updatePartControllerList();
+
+      virtual void paintControllerCanvas(QPainter&, QRect);
+      virtual void paintControllerPanel(QPainter&, QRect);
+
+      void setCursor();
+
+   private slots:
+      void removeController(QAction*);
 
    public slots:
       void songChanged(int type);
 
+   signals:
+      void yChanged(int);  // emitted from mouseMove in controller canvas
+
    public:
       WaveView(WaveEdit*);
       QString getCaption() const;
       void cmd(const QString&);
       void range(AL::Pos&, AL::Pos&) const;
+      void addController(int id, int h);
+      void layout1();
+      const CtrlEditList* getCtrlEditors() const { return &ctrlEditList; }
       };
 
 #endif
-- 
cgit v1.2.3