mirror of https://github.com/AxioDL/amuse.git
Work on SoundMacroEditor
This commit is contained in:
parent
321c2d9a3c
commit
441a3dbfd9
|
@ -33,4 +33,9 @@ QString SysStringToQString(const boo::SystemString& str);
|
||||||
bool MkPath(const QString& path, UIMessenger& messenger);
|
bool MkPath(const QString& path, UIMessenger& messenger);
|
||||||
bool MkPath(const QDir& dir, const QString& file, UIMessenger& messenger);
|
bool MkPath(const QDir& dir, const QString& file, UIMessenger& messenger);
|
||||||
|
|
||||||
|
static QLatin1String StringViewToQString(std::string_view sv)
|
||||||
|
{
|
||||||
|
return QLatin1String(sv.data(), int(sv.size()));
|
||||||
|
}
|
||||||
|
|
||||||
#endif //AMUSE_COMMON_HPP
|
#endif //AMUSE_COMMON_HPP
|
||||||
|
|
|
@ -3,8 +3,10 @@
|
||||||
#include <QSvgRenderer>
|
#include <QSvgRenderer>
|
||||||
#include <QMouseEvent>
|
#include <QMouseEvent>
|
||||||
#include <QScrollArea>
|
#include <QScrollArea>
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QScrollBar>
|
||||||
|
|
||||||
/* Used for generating transform matrices to map coordinate space */
|
/* Used for generating transform matrices to map SVG coordinate space */
|
||||||
static QTransform RectToRect(const QRectF& from, const QRectF& to)
|
static QTransform RectToRect(const QRectF& from, const QRectF& to)
|
||||||
{
|
{
|
||||||
QPolygonF orig(from);
|
QPolygonF orig(from);
|
||||||
|
@ -193,6 +195,15 @@ void KeyboardWidget::leaveEvent(QEvent* event)
|
||||||
m_statusFocus->exit();
|
m_statusFocus->exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void KeyboardWidget::wheelEvent(QWheelEvent* event)
|
||||||
|
{
|
||||||
|
if (QScrollArea* scroll = qobject_cast<QScrollArea*>(parentWidget()->parentWidget()))
|
||||||
|
{
|
||||||
|
/* Send wheel event directly to the scroll bar */
|
||||||
|
QApplication::sendEvent(scroll->horizontalScrollBar(), event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void KeyboardWidget::showEvent(QShowEvent* event)
|
void KeyboardWidget::showEvent(QShowEvent* event)
|
||||||
{
|
{
|
||||||
if (QScrollArea* scroll = qobject_cast<QScrollArea*>(parentWidget()->parentWidget()))
|
if (QScrollArea* scroll = qobject_cast<QScrollArea*>(parentWidget()->parentWidget()))
|
||||||
|
|
|
@ -45,6 +45,7 @@ public:
|
||||||
void mouseReleaseEvent(QMouseEvent* event);
|
void mouseReleaseEvent(QMouseEvent* event);
|
||||||
void enterEvent(QEvent* event);
|
void enterEvent(QEvent* event);
|
||||||
void leaveEvent(QEvent* event);
|
void leaveEvent(QEvent* event);
|
||||||
|
void wheelEvent(QWheelEvent *event);
|
||||||
void showEvent(QShowEvent *event);
|
void showEvent(QShowEvent *event);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,7 @@ MainWindow::MainWindow(QWidget* parent)
|
||||||
m_backgroundThread.start();
|
m_backgroundThread.start();
|
||||||
|
|
||||||
m_ui.setupUi(this);
|
m_ui.setupUi(this);
|
||||||
|
m_ui.splitter->setCollapsible(1, false);
|
||||||
m_ui.projectOutline->setItemDelegate(&m_treeDelegate);
|
m_ui.projectOutline->setItemDelegate(&m_treeDelegate);
|
||||||
connectMessenger(&m_mainMessenger, Qt::DirectConnection);
|
connectMessenger(&m_mainMessenger, Qt::DirectConnection);
|
||||||
|
|
||||||
|
@ -252,6 +253,7 @@ bool MainWindow::_setEditor(EditorWidget* editor)
|
||||||
}
|
}
|
||||||
m_ui.editorContents->addWidget(editor);
|
m_ui.editorContents->addWidget(editor);
|
||||||
m_ui.editorContents->setCurrentWidget(editor);
|
m_ui.editorContents->setCurrentWidget(editor);
|
||||||
|
m_ui.editorContents->update();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,8 +6,8 @@
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>800</width>
|
<width>1024</width>
|
||||||
<height>600</height>
|
<height>768</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
|
@ -98,8 +98,8 @@
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>540</width>
|
<width>764</width>
|
||||||
<height>442</height>
|
<height>610</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
|
@ -174,13 +174,13 @@
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>800</width>
|
<width>1024</width>
|
||||||
<height>27</height>
|
<height>27</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QMenu" name="menuFile">
|
<widget class="QMenu" name="menuFile">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Fi&le</string>
|
<string>&File</string>
|
||||||
</property>
|
</property>
|
||||||
<addaction name="actionNew_Project"/>
|
<addaction name="actionNew_Project"/>
|
||||||
<addaction name="actionOpen_Project"/>
|
<addaction name="actionOpen_Project"/>
|
||||||
|
@ -204,7 +204,7 @@
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QMenu" name="menuAudio">
|
<widget class="QMenu" name="menuAudio">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>A&udio</string>
|
<string>&Audio</string>
|
||||||
</property>
|
</property>
|
||||||
<addaction name="actionAuto_Play"/>
|
<addaction name="actionAuto_Play"/>
|
||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
|
@ -219,7 +219,7 @@
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QMenu" name="menuEdit">
|
<widget class="QMenu" name="menuEdit">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Edit</string>
|
<string>&Edit</string>
|
||||||
</property>
|
</property>
|
||||||
<addaction name="actionUndo"/>
|
<addaction name="actionUndo"/>
|
||||||
<addaction name="actionRedo"/>
|
<addaction name="actionRedo"/>
|
||||||
|
|
|
@ -1,14 +1,16 @@
|
||||||
#include "SoundMacroEditor.hpp"
|
#include "SoundMacroEditor.hpp"
|
||||||
#include <QLabel>
|
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <QPropertyAnimation>
|
#include <QPropertyAnimation>
|
||||||
#include <QVBoxLayout>
|
|
||||||
#include <QGridLayout>
|
#include <QGridLayout>
|
||||||
#include <QLineEdit>
|
#include <QLineEdit>
|
||||||
#include <QSpinBox>
|
#include <QSplitter>
|
||||||
|
#include <QScrollArea>
|
||||||
|
#include <QScrollBar>
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QCheckBox>
|
||||||
|
|
||||||
CommandWidget::CommandWidget(QWidget* parent, const QString& text)
|
CommandWidget::CommandWidget(amuse::SoundMacro::ICmd* cmd, amuse::SoundMacro::CmdOp op, QWidget* parent)
|
||||||
: QWidget(parent), m_numberText(text), m_titleText("Command")
|
: QWidget(parent), m_cmd(cmd), m_introspection(amuse::SoundMacro::GetCmdIntrospection(op))
|
||||||
{
|
{
|
||||||
m_titleFont.setWeight(QFont::Bold);
|
m_titleFont.setWeight(QFont::Bold);
|
||||||
m_numberText.setTextOption(QTextOption(Qt::AlignRight));
|
m_numberText.setTextOption(QTextOption(Qt::AlignRight));
|
||||||
|
@ -19,55 +21,167 @@ CommandWidget::CommandWidget(QWidget* parent, const QString& text)
|
||||||
m_numberFont.setStyleHint(QFont::Monospace);
|
m_numberFont.setStyleHint(QFont::Monospace);
|
||||||
m_numberFont.setPointSize(16);
|
m_numberFont.setPointSize(16);
|
||||||
|
|
||||||
#if 0
|
|
||||||
const amuse::SoundMacro::CmdIntrospection* introspection = amuse::SoundMacro::GetCmdIntrospection(cmd->Isa());
|
|
||||||
if (introspection)
|
|
||||||
{
|
|
||||||
for (int f = 0; f < 7; ++f)
|
|
||||||
{
|
|
||||||
introspection->m_fields[f];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
setContentsMargins(54, 4, 0, 4);
|
setContentsMargins(54, 4, 0, 4);
|
||||||
|
|
||||||
QVBoxLayout* mainLayout = new QVBoxLayout;
|
QVBoxLayout* mainLayout = new QVBoxLayout;
|
||||||
mainLayout->addStretch();
|
mainLayout->addStretch();
|
||||||
|
|
||||||
QGridLayout* layout = new QGridLayout;
|
QGridLayout* layout = new QGridLayout;
|
||||||
layout->addWidget(new QLabel("One"), 0, 0);
|
if (m_introspection)
|
||||||
layout->addWidget(new QSpinBox, 1, 0);
|
{
|
||||||
layout->addWidget(new QLabel("Two"), 0, 1);
|
m_titleText.setText(StringViewToQString(m_introspection->m_name));
|
||||||
layout->addWidget(new QSpinBox, 1, 1);
|
for (int f = 0; f < 7; ++f)
|
||||||
layout->addWidget(new QLabel("Three"), 0, 2);
|
{
|
||||||
layout->addWidget(new QSpinBox, 1, 2);
|
const amuse::SoundMacro::CmdIntrospection::Field& field = m_introspection->m_fields[f];
|
||||||
|
if (!field.m_name.empty())
|
||||||
|
{
|
||||||
|
layout->addWidget(new QLabel(StringViewToQString(field.m_name)), 0, f);
|
||||||
|
switch (field.m_tp)
|
||||||
|
{
|
||||||
|
case amuse::SoundMacro::CmdIntrospection::Field::Type::Bool:
|
||||||
|
{
|
||||||
|
QCheckBox* cb = new QCheckBox;
|
||||||
|
cb->setProperty("fieldIndex", f);
|
||||||
|
cb->setCheckState(field.m_default ? Qt::Checked : Qt::Unchecked);
|
||||||
|
connect(cb, SIGNAL(stateChanged(int)), this, SLOT(boolChanged(int)));
|
||||||
|
layout->addWidget(cb, 1, f);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case amuse::SoundMacro::CmdIntrospection::Field::Type::Int8:
|
||||||
|
case amuse::SoundMacro::CmdIntrospection::Field::Type::UInt8:
|
||||||
|
case amuse::SoundMacro::CmdIntrospection::Field::Type::Int16:
|
||||||
|
case amuse::SoundMacro::CmdIntrospection::Field::Type::UInt16:
|
||||||
|
case amuse::SoundMacro::CmdIntrospection::Field::Type::Int32:
|
||||||
|
case amuse::SoundMacro::CmdIntrospection::Field::Type::UInt32:
|
||||||
|
{
|
||||||
|
FieldSpinBox* sb = new FieldSpinBox;
|
||||||
|
sb->setProperty("fieldIndex", f);
|
||||||
|
sb->setMinimum(int(field.m_min));
|
||||||
|
sb->setMaximum(int(field.m_max));
|
||||||
|
sb->setValue(int(field.m_default));
|
||||||
|
connect(sb, SIGNAL(valueChanged(int)), this, SLOT(numChanged(int)));
|
||||||
|
layout->addWidget(sb, 1, f);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
mainLayout->addLayout(layout);
|
mainLayout->addLayout(layout);
|
||||||
|
|
||||||
setLayout(mainLayout);
|
setLayout(mainLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CommandWidget::CommandWidget(amuse::SoundMacro::ICmd* cmd, QWidget* parent)
|
||||||
|
: CommandWidget(cmd, cmd->Isa(), parent) {}
|
||||||
|
|
||||||
|
CommandWidget::CommandWidget(amuse::SoundMacro::CmdOp op, QWidget* parent)
|
||||||
|
: CommandWidget(nullptr, op, parent) {}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static T& AccessField(amuse::SoundMacro::ICmd* cmd, const amuse::SoundMacro::CmdIntrospection::Field& field)
|
||||||
|
{
|
||||||
|
return *reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(std::addressof(*cmd)) + field.m_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommandWidget::boolChanged(int state)
|
||||||
|
{
|
||||||
|
if (m_introspection)
|
||||||
|
{
|
||||||
|
QCheckBox* cb = static_cast<QCheckBox*>(sender());
|
||||||
|
const amuse::SoundMacro::CmdIntrospection::Field& field =
|
||||||
|
m_introspection->m_fields[cb->property("fieldIndex").toInt()];
|
||||||
|
AccessField<bool>(m_cmd, field) = state == Qt::Checked;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommandWidget::numChanged(int value)
|
||||||
|
{
|
||||||
|
if (m_introspection)
|
||||||
|
{
|
||||||
|
FieldSpinBox* sb = static_cast<FieldSpinBox*>(sender());
|
||||||
|
const amuse::SoundMacro::CmdIntrospection::Field& field =
|
||||||
|
m_introspection->m_fields[sb->property("fieldIndex").toInt()];
|
||||||
|
switch (field.m_tp)
|
||||||
|
{
|
||||||
|
case amuse::SoundMacro::CmdIntrospection::Field::Type::Int8:
|
||||||
|
AccessField<int8_t>(m_cmd, field) = int8_t(value);
|
||||||
|
break;
|
||||||
|
case amuse::SoundMacro::CmdIntrospection::Field::Type::UInt8:
|
||||||
|
AccessField<uint8_t>(m_cmd, field) = uint8_t(value);
|
||||||
|
break;
|
||||||
|
case amuse::SoundMacro::CmdIntrospection::Field::Type::Int16:
|
||||||
|
AccessField<int16_t>(m_cmd, field) = int16_t(value);
|
||||||
|
break;
|
||||||
|
case amuse::SoundMacro::CmdIntrospection::Field::Type::UInt16:
|
||||||
|
AccessField<uint16_t>(m_cmd, field) = uint16_t(value);
|
||||||
|
break;
|
||||||
|
case amuse::SoundMacro::CmdIntrospection::Field::Type::Int32:
|
||||||
|
AccessField<int32_t>(m_cmd, field) = int32_t(value);
|
||||||
|
break;
|
||||||
|
case amuse::SoundMacro::CmdIntrospection::Field::Type::UInt32:
|
||||||
|
AccessField<uint32_t>(m_cmd, field) = uint32_t(value);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CommandWidget::animateOpen()
|
void CommandWidget::animateOpen()
|
||||||
{
|
{
|
||||||
QPropertyAnimation* animation = new QPropertyAnimation(this, "minimumHeight");
|
int newHeight = 200 + parentWidget()->layout()->spacing();
|
||||||
animation->setDuration(abs(minimumHeight() - 200) * 3);
|
m_animation = new QPropertyAnimation(this, "minimumHeight");
|
||||||
animation->setStartValue(minimumHeight());
|
m_animation->setDuration(abs(minimumHeight() - newHeight) * 4);
|
||||||
animation->setEndValue(200);
|
m_animation->setStartValue(minimumHeight());
|
||||||
animation->setEasingCurve(QEasingCurve::InOutExpo);
|
m_animation->setEndValue(newHeight);
|
||||||
connect(animation, SIGNAL(valueChanged(const QVariant&)), parentWidget(), SLOT(update()));
|
m_animation->setEasingCurve(QEasingCurve::InOutExpo);
|
||||||
animation->start(QAbstractAnimation::DeleteWhenStopped);
|
connect(m_animation, SIGNAL(valueChanged(const QVariant&)), parentWidget(), SLOT(update()));
|
||||||
|
connect(m_animation, SIGNAL(destroyed(QObject*)), this, SLOT(animationDestroyed()));
|
||||||
|
m_animation->start(QAbstractAnimation::DeleteWhenStopped);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandWidget::animateClosed()
|
void CommandWidget::animateClosed()
|
||||||
{
|
{
|
||||||
QPropertyAnimation* animation = new QPropertyAnimation(this, "minimumHeight");
|
m_animation = new QPropertyAnimation(this, "minimumHeight");
|
||||||
animation->setDuration(abs(minimumHeight() - 100) * 3);
|
m_animation->setDuration(abs(minimumHeight() - 100) * 4);
|
||||||
animation->setStartValue(minimumHeight());
|
m_animation->setStartValue(minimumHeight());
|
||||||
animation->setEndValue(100);
|
m_animation->setEndValue(100);
|
||||||
animation->setEasingCurve(QEasingCurve::InOutExpo);
|
m_animation->setEasingCurve(QEasingCurve::InOutExpo);
|
||||||
connect(animation, SIGNAL(valueChanged(const QVariant&)), parentWidget(), SLOT(update()));
|
connect(m_animation, SIGNAL(valueChanged(const QVariant&)), parentWidget(), SLOT(update()));
|
||||||
animation->start(QAbstractAnimation::DeleteWhenStopped);
|
connect(m_animation, SIGNAL(destroyed(QObject*)), this, SLOT(animationDestroyed()));
|
||||||
|
m_animation->start(QAbstractAnimation::DeleteWhenStopped);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommandWidget::snapOpen()
|
||||||
|
{
|
||||||
|
if (m_animation)
|
||||||
|
m_animation->stop();
|
||||||
|
setMinimumHeight(200 + parentWidget()->layout()->spacing());
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommandWidget::snapClosed()
|
||||||
|
{
|
||||||
|
if (m_animation)
|
||||||
|
m_animation->stop();
|
||||||
|
setMinimumHeight(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommandWidget::setIndex(int index)
|
||||||
|
{
|
||||||
|
m_numberText.setText(QString::number(index));
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommandWidget::animationDestroyed()
|
||||||
|
{
|
||||||
|
m_animation = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
SoundMacroListing* CommandWidget::getParent() const
|
||||||
|
{
|
||||||
|
return qobject_cast<SoundMacroListing*>(parentWidget());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandWidget::paintEvent(QPaintEvent* event)
|
void CommandWidget::paintEvent(QPaintEvent* event)
|
||||||
|
@ -75,8 +189,6 @@ void CommandWidget::paintEvent(QPaintEvent* event)
|
||||||
/* Rounded frame */
|
/* Rounded frame */
|
||||||
QPainter painter(this);
|
QPainter painter(this);
|
||||||
painter.setRenderHint(QPainter::Antialiasing);
|
painter.setRenderHint(QPainter::Antialiasing);
|
||||||
painter.setPen(QPen(QColor(127, 127, 127), 2.0));
|
|
||||||
painter.setBrush(QColor(127, 127, 127));
|
|
||||||
|
|
||||||
QTransform mainXf = QTransform::fromTranslate(0, rect().bottom() - 99);
|
QTransform mainXf = QTransform::fromTranslate(0, rect().bottom() - 99);
|
||||||
painter.setTransform(mainXf);
|
painter.setTransform(mainXf);
|
||||||
|
@ -87,8 +199,11 @@ void CommandWidget::paintEvent(QPaintEvent* event)
|
||||||
{width() - 1, 99},
|
{width() - 1, 99},
|
||||||
{width() - 1, 1},
|
{width() - 1, 1},
|
||||||
{20, 1},
|
{20, 1},
|
||||||
{1, 20}
|
{1, 20},
|
||||||
};
|
};
|
||||||
|
painter.setBrush(palette().brush(QPalette::Background));
|
||||||
|
painter.drawPolygon(points, 6);
|
||||||
|
painter.setPen(QPen(QColor(127, 127, 127), 2.0));
|
||||||
painter.drawPolyline(points, 6);
|
painter.drawPolyline(points, 6);
|
||||||
|
|
||||||
QPoint headPoints[] =
|
QPoint headPoints[] =
|
||||||
|
@ -101,6 +216,7 @@ void CommandWidget::paintEvent(QPaintEvent* event)
|
||||||
{20, 1},
|
{20, 1},
|
||||||
{1, 20}
|
{1, 20}
|
||||||
};
|
};
|
||||||
|
painter.setBrush(QColor(127, 127, 127));
|
||||||
painter.drawPolygon(headPoints, 7);
|
painter.drawPolygon(headPoints, 7);
|
||||||
|
|
||||||
painter.drawRect(17, 51, 32, 32);
|
painter.drawRect(17, 51, 32, 32);
|
||||||
|
@ -114,27 +230,415 @@ void CommandWidget::paintEvent(QPaintEvent* event)
|
||||||
painter.setTransform(rotate * mainXf);
|
painter.setTransform(rotate * mainXf);
|
||||||
painter.setFont(m_numberFont);
|
painter.setFont(m_numberFont);
|
||||||
painter.drawStaticText(-15, 10, m_numberText);
|
painter.drawStaticText(-15, 10, m_numberText);
|
||||||
|
|
||||||
QWidget::paintEvent(event);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandWidget::mousePressEvent(QMouseEvent* event)
|
void SoundMacroListing::startAutoscroll(QWidget* source, QMouseEvent* event, int delta)
|
||||||
{
|
{
|
||||||
animateOpen();
|
if (m_autoscrollTimer == -1)
|
||||||
|
m_autoscrollTimer = startTimer(50);
|
||||||
|
m_autoscrollDelta = delta;
|
||||||
|
m_autoscrollSource = source;
|
||||||
|
m_autoscrollEvent = *event;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandWidget::mouseReleaseEvent(QMouseEvent* event)
|
void SoundMacroListing::stopAutoscroll()
|
||||||
{
|
{
|
||||||
animateClosed();
|
if (m_autoscrollTimer != -1)
|
||||||
|
{
|
||||||
|
killTimer(m_autoscrollTimer);
|
||||||
|
m_autoscrollTimer = -1;
|
||||||
|
}
|
||||||
|
m_autoscrollDelta = 0;
|
||||||
|
m_autoscrollSource = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
SoundMacroEditor::SoundMacroEditor(ProjectModel::SoundMacroNode* node, QWidget* parent)
|
void SoundMacroListing::timerEvent(QTimerEvent* event)
|
||||||
: EditorWidget(parent)
|
{
|
||||||
|
if (QScrollArea* scrollArea = qobject_cast<QScrollArea*>(parentWidget()->parentWidget()))
|
||||||
|
{
|
||||||
|
QScrollBar* bar = scrollArea->verticalScrollBar();
|
||||||
|
int oldValue = bar->value();
|
||||||
|
bar->setValue(oldValue + m_autoscrollDelta);
|
||||||
|
int valueDelta = bar->value() - oldValue;
|
||||||
|
if (valueDelta != 0)
|
||||||
|
{
|
||||||
|
if (m_autoscrollSource)
|
||||||
|
QApplication::sendEvent(m_autoscrollSource, &m_autoscrollEvent);
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SoundMacroListing::beginDrag(CommandWidget* widget)
|
||||||
|
{
|
||||||
|
int origIdx = m_layout->indexOf(widget);
|
||||||
|
/* Don't allow dragging last command (END command) */
|
||||||
|
if (origIdx < 0 || origIdx >= m_layout->count() - 2)
|
||||||
|
return false;
|
||||||
|
if (origIdx < m_layout->count() - 2)
|
||||||
|
{
|
||||||
|
// Animate next item open
|
||||||
|
m_dragOpenIdx = origIdx;
|
||||||
|
if (CommandWidget* nextItem = qobject_cast<CommandWidget*>(m_layout->itemAt(origIdx + 1)->widget()))
|
||||||
|
nextItem->snapOpen();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_dragOpenIdx = -1;
|
||||||
|
}
|
||||||
|
m_origIdx = origIdx;
|
||||||
|
m_dragItem = m_layout->takeAt(origIdx);
|
||||||
|
m_dragItem->widget()->raise();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoundMacroListing::endDrag(CommandWidget* widget)
|
||||||
|
{
|
||||||
|
if (m_dragOpenIdx != -1)
|
||||||
|
{
|
||||||
|
if (CommandWidget* prevItem = qobject_cast<CommandWidget*>(m_layout->itemAt(m_dragOpenIdx)->widget()))
|
||||||
|
prevItem->snapClosed();
|
||||||
|
m_layout->insertItem(m_dragOpenIdx, m_dragItem);
|
||||||
|
m_dragOpenIdx = -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_layout->insertItem(m_layout->count() - 2, m_dragItem);
|
||||||
|
}
|
||||||
|
if (m_prevDragOpen)
|
||||||
|
{
|
||||||
|
m_prevDragOpen->snapClosed();
|
||||||
|
m_prevDragOpen = nullptr;
|
||||||
|
}
|
||||||
|
m_dragItem = nullptr;
|
||||||
|
stopAutoscroll();
|
||||||
|
reindex();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoundMacroListing::cancelDrag()
|
||||||
|
{
|
||||||
|
if (m_dragOpenIdx != -1)
|
||||||
|
{
|
||||||
|
if (CommandWidget* prevItem = qobject_cast<CommandWidget*>(m_layout->itemAt(m_dragOpenIdx)->widget()))
|
||||||
|
prevItem->snapClosed();
|
||||||
|
m_dragOpenIdx = -1;
|
||||||
|
}
|
||||||
|
m_layout->insertItem(m_origIdx, m_dragItem);
|
||||||
|
if (m_prevDragOpen)
|
||||||
|
{
|
||||||
|
m_prevDragOpen->snapClosed();
|
||||||
|
m_prevDragOpen = nullptr;
|
||||||
|
}
|
||||||
|
m_dragItem = nullptr;
|
||||||
|
stopAutoscroll();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoundMacroListing::_moveDrag(int hoverIdx, const QPoint& pt, QWidget* source, QMouseEvent* event)
|
||||||
|
{
|
||||||
|
QRect scrollVpRect = parentWidget()->parentWidget()->rect();
|
||||||
|
QPoint scrollVpPoint = mapTo(parentWidget()->parentWidget(), pt);
|
||||||
|
if (scrollVpRect.bottom() - scrollVpPoint.y() < 50)
|
||||||
|
startAutoscroll(source, event, 10); // Scroll Down
|
||||||
|
else if (scrollVpRect.top() - scrollVpPoint.y() > -50)
|
||||||
|
startAutoscroll(source, event, -10);
|
||||||
|
else
|
||||||
|
stopAutoscroll();
|
||||||
|
|
||||||
|
/* Don't allow insertion after last command (END command) */
|
||||||
|
hoverIdx = std::max(0, std::min(hoverIdx, m_layout->count() - 2));
|
||||||
|
if (hoverIdx != m_dragOpenIdx)
|
||||||
|
{
|
||||||
|
if (m_dragOpenIdx != -1)
|
||||||
|
if (CommandWidget* prevItem = qobject_cast<CommandWidget*>(m_layout->itemAt(m_dragOpenIdx)->widget()))
|
||||||
|
{
|
||||||
|
m_prevDragOpen = prevItem;
|
||||||
|
prevItem->animateClosed();
|
||||||
|
}
|
||||||
|
if (CommandWidget* nextItem = qobject_cast<CommandWidget*>(m_layout->itemAt(hoverIdx)->widget()))
|
||||||
|
nextItem->animateOpen();
|
||||||
|
m_dragOpenIdx = hoverIdx;
|
||||||
|
}
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoundMacroListing::moveDrag(CommandWidget* widget, const QPoint& pt, QWidget* source, QMouseEvent* event)
|
||||||
|
{
|
||||||
|
int pitch = 100 + m_layout->spacing();
|
||||||
|
_moveDrag((widget->pos().y() - m_layout->contentsMargins().top() + pitch / 2) / pitch, pt, source, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
int SoundMacroListing::moveInsertDrag(const QPoint& pt, QWidget* source, QMouseEvent* event)
|
||||||
|
{
|
||||||
|
int pitch = 100 + m_layout->spacing();
|
||||||
|
_moveDrag(pt.y() / pitch, pt, source, event);
|
||||||
|
return m_dragOpenIdx;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoundMacroListing::insertDragout()
|
||||||
|
{
|
||||||
|
if (m_dragOpenIdx != -1)
|
||||||
|
{
|
||||||
|
if (CommandWidget* prevItem = qobject_cast<CommandWidget*>(m_layout->itemAt(m_dragOpenIdx)->widget()))
|
||||||
|
{
|
||||||
|
m_prevDragOpen = prevItem;
|
||||||
|
prevItem->animateClosed();
|
||||||
|
}
|
||||||
|
m_dragOpenIdx = -1;
|
||||||
|
}
|
||||||
|
stopAutoscroll();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoundMacroListing::insert(amuse::SoundMacro::CmdOp op)
|
||||||
|
{
|
||||||
|
CommandWidget* newCmd = new CommandWidget(amuse::SoundMacro::MakeCmd(op).release(), this);
|
||||||
|
if (m_dragOpenIdx != -1)
|
||||||
|
{
|
||||||
|
if (CommandWidget* prevItem = qobject_cast<CommandWidget*>(m_layout->itemAt(m_dragOpenIdx)->widget()))
|
||||||
|
prevItem->snapClosed();
|
||||||
|
m_layout->insertWidget(m_dragOpenIdx, newCmd);
|
||||||
|
m_dragOpenIdx = -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_layout->insertWidget(m_layout->count() - 2, newCmd);
|
||||||
|
}
|
||||||
|
if (m_prevDragOpen)
|
||||||
|
{
|
||||||
|
m_prevDragOpen->snapClosed();
|
||||||
|
m_prevDragOpen = nullptr;
|
||||||
|
}
|
||||||
|
stopAutoscroll();
|
||||||
|
reindex();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoundMacroListing::reindex()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < m_layout->count() - 1; ++i)
|
||||||
|
if (CommandWidget* item = qobject_cast<CommandWidget*>(m_layout->itemAt(i)->widget()))
|
||||||
|
item->setIndex(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
SoundMacroListing::SoundMacroListing(ProjectModel::SoundMacroNode* node, QWidget* parent)
|
||||||
|
: QWidget(parent), m_layout(new QVBoxLayout)
|
||||||
|
{
|
||||||
|
m_layout->addWidget(new CommandWidget(amuse::SoundMacro::CmdOp::End, this));
|
||||||
|
m_layout->addStretch();
|
||||||
|
setLayout(m_layout);
|
||||||
|
reindex();
|
||||||
|
}
|
||||||
|
|
||||||
|
CatalogueItem::CatalogueItem(amuse::SoundMacro::CmdOp op, const QString& name,
|
||||||
|
const QString& doc, QWidget* parent)
|
||||||
|
: QWidget(parent), m_op(op)
|
||||||
|
{
|
||||||
|
QHBoxLayout* layout = new QHBoxLayout;
|
||||||
|
QLabel* iconLab = new QLabel;
|
||||||
|
iconLab->setPixmap(QIcon(":/icons/IconOpen.svg").pixmap(32, 32));
|
||||||
|
layout->addWidget(iconLab);
|
||||||
|
layout->addWidget(new QLabel(name));
|
||||||
|
layout->addStretch();
|
||||||
|
layout->setContentsMargins(QMargins());
|
||||||
|
setLayout(layout);
|
||||||
|
setToolTip(doc);
|
||||||
|
}
|
||||||
|
|
||||||
|
CatalogueItem::CatalogueItem(const CatalogueItem& other, QWidget* parent)
|
||||||
|
: QWidget(parent), m_op(other.getCmdOp())
|
||||||
|
{
|
||||||
|
QHBoxLayout* layout = new QHBoxLayout;
|
||||||
|
QHBoxLayout* oldLayout = static_cast<QHBoxLayout*>(other.layout());
|
||||||
|
QLabel* iconLab = new QLabel;
|
||||||
|
iconLab->setPixmap(*static_cast<QLabel*>(oldLayout->itemAt(0)->widget())->pixmap());
|
||||||
|
layout->addWidget(iconLab);
|
||||||
|
layout->addWidget(new QLabel(static_cast<QLabel*>(oldLayout->itemAt(1)->widget())->text()));
|
||||||
|
layout->addStretch();
|
||||||
|
layout->setContentsMargins(QMargins());
|
||||||
|
setLayout(layout);
|
||||||
|
}
|
||||||
|
|
||||||
|
SoundMacroCatalogue::SoundMacroCatalogue(QWidget* parent)
|
||||||
|
: QWidget(parent)
|
||||||
{
|
{
|
||||||
QVBoxLayout* layout = new QVBoxLayout;
|
QVBoxLayout* layout = new QVBoxLayout;
|
||||||
layout->addWidget(new CommandWidget(this, "1"));
|
for (int i = 1; i < int(amuse::SoundMacro::CmdOp::CmdOpMAX); ++i)
|
||||||
layout->addWidget(new CommandWidget(this, "42"));
|
{
|
||||||
layout->addWidget(new CommandWidget(this, "99"));
|
const amuse::SoundMacro::CmdIntrospection* cmd =
|
||||||
|
amuse::SoundMacro::GetCmdIntrospection(amuse::SoundMacro::CmdOp(i));
|
||||||
|
if (cmd)
|
||||||
|
{
|
||||||
|
layout->addWidget(new CatalogueItem(amuse::SoundMacro::CmdOp(i), StringViewToQString(cmd->m_name),
|
||||||
|
StringViewToQString(cmd->m_description)));
|
||||||
|
}
|
||||||
|
}
|
||||||
layout->addStretch();
|
layout->addStretch();
|
||||||
setLayout(layout);
|
setLayout(layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SoundMacroEditor::beginCommandDrag(CommandWidget* widget, const QPoint& eventPt, const QPoint& pt)
|
||||||
|
{
|
||||||
|
if (m_listing->beginDrag(widget))
|
||||||
|
{
|
||||||
|
m_draggedPt = pt;
|
||||||
|
m_draggedCmd = widget;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoundMacroEditor::beginCatalogueDrag(CatalogueItem* item, const QPoint& eventPt, const QPoint& pt)
|
||||||
|
{
|
||||||
|
m_draggedPt = pt;
|
||||||
|
m_draggedItem = new CatalogueItem(*item, this);
|
||||||
|
m_draggedItem->setGeometry(item->geometry());
|
||||||
|
m_draggedItem->move(eventPt - m_draggedPt);
|
||||||
|
m_draggedItem->raise();
|
||||||
|
m_draggedItem->show();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoundMacroEditor::mousePressEvent(QMouseEvent* event)
|
||||||
|
{
|
||||||
|
if (m_catalogue->parentWidget()->parentWidget()->geometry().contains(event->pos()))
|
||||||
|
{
|
||||||
|
QPoint fromParent1 = m_catalogue->mapFrom(this, event->pos());
|
||||||
|
QWidget* ch = m_catalogue->childAt(fromParent1);
|
||||||
|
if (ch)
|
||||||
|
{
|
||||||
|
CatalogueItem* child = nullptr;
|
||||||
|
while (ch && !(child = qobject_cast<CatalogueItem*>(ch)))
|
||||||
|
ch = ch->parentWidget();
|
||||||
|
if (child)
|
||||||
|
{
|
||||||
|
QPoint fromParent2 = child->mapFrom(m_catalogue, fromParent1);
|
||||||
|
beginCatalogueDrag(child, event->pos(), fromParent2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (m_listing->parentWidget()->parentWidget()->geometry().contains(event->pos()))
|
||||||
|
{
|
||||||
|
QPoint fromParent1 = m_listing->mapFrom(this, event->pos());
|
||||||
|
QWidget* ch = m_listing->childAt(fromParent1);
|
||||||
|
if (ch)
|
||||||
|
{
|
||||||
|
CommandWidget* child = nullptr;
|
||||||
|
while (ch && !(child = qobject_cast<CommandWidget*>(ch)))
|
||||||
|
ch = ch->parentWidget();
|
||||||
|
if (child)
|
||||||
|
{
|
||||||
|
QPoint fromParent2 = child->mapFrom(m_listing, fromParent1);
|
||||||
|
beginCommandDrag(child, event->pos(), fromParent2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoundMacroEditor::mouseReleaseEvent(QMouseEvent* event)
|
||||||
|
{
|
||||||
|
if (m_draggedItem)
|
||||||
|
{
|
||||||
|
amuse::SoundMacro::CmdOp op = m_draggedItem->getCmdOp();
|
||||||
|
m_draggedItem->deleteLater();
|
||||||
|
m_draggedItem = nullptr;
|
||||||
|
|
||||||
|
if (m_listing->parentWidget()->parentWidget()->geometry().contains(event->pos()))
|
||||||
|
{
|
||||||
|
if (m_dragInsertIdx != -1)
|
||||||
|
m_listing->insert(op);
|
||||||
|
else
|
||||||
|
m_listing->insertDragout();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_listing->insertDragout();
|
||||||
|
}
|
||||||
|
m_dragInsertIdx = -1;
|
||||||
|
}
|
||||||
|
else if (m_draggedCmd)
|
||||||
|
{
|
||||||
|
m_listing->endDrag(m_draggedCmd);
|
||||||
|
m_draggedCmd = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoundMacroEditor::mouseMoveEvent(QMouseEvent* event)
|
||||||
|
{
|
||||||
|
if (m_draggedItem)
|
||||||
|
{
|
||||||
|
m_draggedItem->move(event->pos() - m_draggedPt);
|
||||||
|
if (m_listing->parentWidget()->parentWidget()->geometry().contains(event->pos()))
|
||||||
|
{
|
||||||
|
m_dragInsertIdx = m_listing->moveInsertDrag(m_listing->mapFrom(this, event->pos()), this, event);
|
||||||
|
}
|
||||||
|
else if (m_dragInsertIdx != -1)
|
||||||
|
{
|
||||||
|
m_listing->insertDragout();
|
||||||
|
m_dragInsertIdx = -1;
|
||||||
|
}
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
else if (m_draggedCmd)
|
||||||
|
{
|
||||||
|
QPoint listingPt = m_listing->mapFrom(this, event->pos());
|
||||||
|
m_draggedCmd->move(m_draggedCmd->x(), listingPt.y() - m_draggedPt.y());
|
||||||
|
if (m_listing->parentWidget()->parentWidget()->geometry().contains(event->pos()))
|
||||||
|
m_listing->moveDrag(m_draggedCmd, listingPt, this, event);
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoundMacroEditor::keyPressEvent(QKeyEvent* event)
|
||||||
|
{
|
||||||
|
if (event->key() == Qt::Key_Escape)
|
||||||
|
{
|
||||||
|
if (m_draggedItem)
|
||||||
|
{
|
||||||
|
m_draggedItem->deleteLater();
|
||||||
|
m_draggedItem = nullptr;
|
||||||
|
m_listing->insertDragout();
|
||||||
|
}
|
||||||
|
else if (m_draggedCmd)
|
||||||
|
{
|
||||||
|
m_listing->cancelDrag();
|
||||||
|
m_draggedCmd = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SoundMacroEditor::SoundMacroEditor(ProjectModel::SoundMacroNode* node, QWidget* parent)
|
||||||
|
: EditorWidget(parent), m_splitter(new QSplitter),
|
||||||
|
m_listing(new SoundMacroListing(node)), m_catalogue(new SoundMacroCatalogue)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
QScrollArea* listingScroll = new QScrollArea;
|
||||||
|
listingScroll->setWidget(m_listing);
|
||||||
|
listingScroll->setWidgetResizable(true);
|
||||||
|
QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
|
||||||
|
sizePolicy.setHorizontalStretch(1);
|
||||||
|
sizePolicy.setVerticalStretch(0);
|
||||||
|
listingScroll->setSizePolicy(sizePolicy);
|
||||||
|
listingScroll->setMinimumWidth(350);
|
||||||
|
m_splitter->addWidget(listingScroll);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
QScrollArea* catalogueScroll = new QScrollArea;
|
||||||
|
catalogueScroll->setWidget(m_catalogue);
|
||||||
|
catalogueScroll->setWidgetResizable(true);
|
||||||
|
QSizePolicy sizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
|
||||||
|
sizePolicy.setHorizontalStretch(0);
|
||||||
|
sizePolicy.setVerticalStretch(0);
|
||||||
|
catalogueScroll->setSizePolicy(sizePolicy);
|
||||||
|
catalogueScroll->setMinimumWidth(150);
|
||||||
|
catalogueScroll->setGeometry(0, 0, 215, 0);
|
||||||
|
catalogueScroll->setMaximumWidth(300);
|
||||||
|
catalogueScroll->setBackgroundRole(QPalette::Base);
|
||||||
|
catalogueScroll->setAutoFillBackground(true);
|
||||||
|
catalogueScroll->setFrameShape(QFrame::StyledPanel);
|
||||||
|
catalogueScroll->setFrameShadow(QFrame::Sunken);
|
||||||
|
catalogueScroll->setLineWidth(1);
|
||||||
|
m_splitter->addWidget(catalogueScroll);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_splitter->setCollapsible(0, false);
|
||||||
|
QGridLayout* layout = new QGridLayout;
|
||||||
|
layout->setContentsMargins(QMargins());
|
||||||
|
layout->addWidget(m_splitter);
|
||||||
|
setLayout(layout);
|
||||||
|
}
|
||||||
|
|
|
@ -3,29 +3,123 @@
|
||||||
|
|
||||||
#include "EditorWidget.hpp"
|
#include "EditorWidget.hpp"
|
||||||
#include <QStaticText>
|
#include <QStaticText>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include <QPropertyAnimation>
|
||||||
|
#include <QSplitter>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QMouseEvent>
|
||||||
|
#include <QSpinBox>
|
||||||
|
|
||||||
|
class SoundMacroListing;
|
||||||
|
class CatalogueItem;
|
||||||
|
|
||||||
|
class FieldSpinBox : public QSpinBox
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
FieldSpinBox(QWidget* parent = Q_NULLPTR)
|
||||||
|
: QSpinBox(parent) {}
|
||||||
|
|
||||||
|
/* Don't scroll */
|
||||||
|
void wheelEvent(QWheelEvent* event) { event->ignore(); }
|
||||||
|
};
|
||||||
|
|
||||||
class CommandWidget : public QWidget
|
class CommandWidget : public QWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
friend class SoundMacroListing;
|
||||||
|
QPropertyAnimation* m_animation = nullptr;
|
||||||
QFont m_numberFont;
|
QFont m_numberFont;
|
||||||
QFont m_titleFont;
|
QFont m_titleFont;
|
||||||
QStaticText m_numberText;
|
QStaticText m_numberText;
|
||||||
QStaticText m_titleText;
|
QStaticText m_titleText;
|
||||||
|
amuse::SoundMacro::ICmd* m_cmd;
|
||||||
|
const amuse::SoundMacro::CmdIntrospection* m_introspection;
|
||||||
void animateOpen();
|
void animateOpen();
|
||||||
void animateClosed();
|
void animateClosed();
|
||||||
|
void snapOpen();
|
||||||
|
void snapClosed();
|
||||||
|
void setIndex(int index);
|
||||||
|
SoundMacroListing* getParent() const;
|
||||||
|
private slots:
|
||||||
|
void animationDestroyed();
|
||||||
|
void boolChanged(int);
|
||||||
|
void numChanged(int);
|
||||||
|
private:
|
||||||
|
CommandWidget(amuse::SoundMacro::ICmd* cmd, amuse::SoundMacro::CmdOp op, QWidget* parent = Q_NULLPTR);
|
||||||
public:
|
public:
|
||||||
CommandWidget(QWidget* parent, const QString& text);
|
CommandWidget(amuse::SoundMacro::ICmd* cmd, QWidget* parent = Q_NULLPTR);
|
||||||
|
CommandWidget(amuse::SoundMacro::CmdOp op, QWidget* parent = Q_NULLPTR);
|
||||||
void paintEvent(QPaintEvent* event);
|
void paintEvent(QPaintEvent* event);
|
||||||
void mousePressEvent(QMouseEvent* event);
|
};
|
||||||
void mouseReleaseEvent(QMouseEvent* event);
|
|
||||||
|
class SoundMacroListing : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
friend class CommandWidget;
|
||||||
|
friend class SoundMacroEditor;
|
||||||
|
QVBoxLayout* m_layout;
|
||||||
|
QLayoutItem* m_dragItem = nullptr;
|
||||||
|
int m_origIdx = -1;
|
||||||
|
int m_dragOpenIdx = -1;
|
||||||
|
CommandWidget* m_prevDragOpen = nullptr;
|
||||||
|
int m_autoscrollTimer = -1;
|
||||||
|
int m_autoscrollDelta = 0;
|
||||||
|
QWidget* m_autoscrollSource = nullptr;
|
||||||
|
QMouseEvent m_autoscrollEvent = {{}, {}, {}, {}, {}};
|
||||||
|
void startAutoscroll(QWidget* source, QMouseEvent* event, int delta);
|
||||||
|
void stopAutoscroll();
|
||||||
|
bool beginDrag(CommandWidget* widget);
|
||||||
|
void endDrag(CommandWidget* widget);
|
||||||
|
void cancelDrag();
|
||||||
|
void _moveDrag(int hoverIdx, const QPoint& pt, QWidget* source, QMouseEvent* event);
|
||||||
|
void moveDrag(CommandWidget* widget, const QPoint& pt, QWidget* source, QMouseEvent* event);
|
||||||
|
int moveInsertDrag(const QPoint& pt, QWidget* source, QMouseEvent* event);
|
||||||
|
void insertDragout();
|
||||||
|
void insert(amuse::SoundMacro::CmdOp op);
|
||||||
|
void reindex();
|
||||||
|
public:
|
||||||
|
explicit SoundMacroListing(ProjectModel::SoundMacroNode* node, QWidget* parent = Q_NULLPTR);
|
||||||
|
void timerEvent(QTimerEvent* event);
|
||||||
|
};
|
||||||
|
|
||||||
|
class CatalogueItem : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
amuse::SoundMacro::CmdOp m_op;
|
||||||
|
public:
|
||||||
|
explicit CatalogueItem(amuse::SoundMacro::CmdOp op, const QString& name,
|
||||||
|
const QString& doc, QWidget* parent = Q_NULLPTR);
|
||||||
|
explicit CatalogueItem(const CatalogueItem& other, QWidget* parent = Q_NULLPTR);
|
||||||
|
amuse::SoundMacro::CmdOp getCmdOp() const { return m_op; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class SoundMacroCatalogue : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit SoundMacroCatalogue(QWidget* parent = Q_NULLPTR);
|
||||||
};
|
};
|
||||||
|
|
||||||
class SoundMacroEditor : public EditorWidget
|
class SoundMacroEditor : public EditorWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
QSplitter* m_splitter;
|
||||||
|
SoundMacroListing* m_listing;
|
||||||
|
SoundMacroCatalogue* m_catalogue;
|
||||||
|
CommandWidget* m_draggedCmd = nullptr;
|
||||||
|
CatalogueItem* m_draggedItem = nullptr;
|
||||||
|
QPoint m_draggedPt;
|
||||||
|
int m_dragInsertIdx = -1;
|
||||||
|
void beginCommandDrag(CommandWidget* widget, const QPoint& eventPt, const QPoint& pt);
|
||||||
|
void beginCatalogueDrag(CatalogueItem* item, const QPoint& eventPt, const QPoint& pt);
|
||||||
public:
|
public:
|
||||||
explicit SoundMacroEditor(ProjectModel::SoundMacroNode* node, QWidget* parent = Q_NULLPTR);
|
explicit SoundMacroEditor(ProjectModel::SoundMacroNode* node, QWidget* parent = Q_NULLPTR);
|
||||||
|
|
||||||
|
void mousePressEvent(QMouseEvent* event);
|
||||||
|
void mouseReleaseEvent(QMouseEvent* event);
|
||||||
|
void mouseMoveEvent(QMouseEvent* event);
|
||||||
|
void keyPressEvent(QKeyEvent* event);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -121,6 +121,7 @@ struct SoundMacro
|
||||||
SetVar,
|
SetVar,
|
||||||
IfEqual = 0x70,
|
IfEqual = 0x70,
|
||||||
IfLess,
|
IfLess,
|
||||||
|
CmdOpMAX,
|
||||||
Invalid = 0xff
|
Invalid = 0xff
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1105,6 +1106,7 @@ struct SoundMacro
|
||||||
|
|
||||||
template <class Op, class O, class... _Args>
|
template <class Op, class O, class... _Args>
|
||||||
static O CmdDo(_Args&&... args);
|
static O CmdDo(_Args&&... args);
|
||||||
|
static std::unique_ptr<SoundMacro::ICmd> MakeCmd(CmdOp op);
|
||||||
static const CmdIntrospection* GetCmdIntrospection(CmdOp op);
|
static const CmdIntrospection* GetCmdIntrospection(CmdOp op);
|
||||||
static std::string_view CmdOpToStr(CmdOp op);
|
static std::string_view CmdOpToStr(CmdOp op);
|
||||||
static CmdOp CmdStrToOp(std::string_view op);
|
static CmdOp CmdStrToOp(std::string_view op);
|
||||||
|
|
|
@ -23,6 +23,15 @@ struct MakeCmdOp
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct MakeDefaultCmdOp
|
||||||
|
{
|
||||||
|
template <class Tp, class R>
|
||||||
|
static std::unique_ptr<SoundMacro::ICmd> Do(R& r)
|
||||||
|
{
|
||||||
|
return std::make_unique<Tp>();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct IntrospectCmdOp
|
struct IntrospectCmdOp
|
||||||
{
|
{
|
||||||
template <class Tp>
|
template <class Tp>
|
||||||
|
@ -546,8 +555,14 @@ O SoundMacro::CmdDo(_Args&&... args)
|
||||||
}
|
}
|
||||||
template std::unique_ptr<SoundMacro::ICmd> SoundMacro::CmdDo<MakeCmdOp>(athena::io::MemoryReader& r);
|
template std::unique_ptr<SoundMacro::ICmd> SoundMacro::CmdDo<MakeCmdOp>(athena::io::MemoryReader& r);
|
||||||
template std::unique_ptr<SoundMacro::ICmd> SoundMacro::CmdDo<MakeCmdOp>(athena::io::YAMLDocReader& r);
|
template std::unique_ptr<SoundMacro::ICmd> SoundMacro::CmdDo<MakeCmdOp>(athena::io::YAMLDocReader& r);
|
||||||
|
template std::unique_ptr<SoundMacro::ICmd> SoundMacro::CmdDo<MakeDefaultCmdOp>(SoundMacro::CmdOp& r);
|
||||||
template const SoundMacro::CmdIntrospection* SoundMacro::CmdDo<IntrospectCmdOp>(SoundMacro::CmdOp& op);
|
template const SoundMacro::CmdIntrospection* SoundMacro::CmdDo<IntrospectCmdOp>(SoundMacro::CmdOp& op);
|
||||||
|
|
||||||
|
std::unique_ptr<SoundMacro::ICmd> SoundMacro::MakeCmd(CmdOp op)
|
||||||
|
{
|
||||||
|
return CmdDo<MakeDefaultCmdOp, std::unique_ptr<SoundMacro::ICmd>>(op);
|
||||||
|
}
|
||||||
|
|
||||||
const SoundMacro::CmdIntrospection* SoundMacro::GetCmdIntrospection(CmdOp op)
|
const SoundMacro::CmdIntrospection* SoundMacro::GetCmdIntrospection(CmdOp op)
|
||||||
{
|
{
|
||||||
return CmdDo<IntrospectCmdOp, const SoundMacro::CmdIntrospection*>(op);
|
return CmdDo<IntrospectCmdOp, const SoundMacro::CmdIntrospection*>(op);
|
||||||
|
|
Loading…
Reference in New Issue