diff --git a/src/plugins/qmldesigner/components/easingpane/easingcontextpane.cpp b/src/plugins/qmldesigner/components/easingpane/easingcontextpane.cpp new file mode 100644 index 00000000000..bc4401283c9 --- /dev/null +++ b/src/plugins/qmldesigner/components/easingpane/easingcontextpane.cpp @@ -0,0 +1,363 @@ +#include "easingcontextpane.h" +#include "ui_easingcontextpane.h" +#include + +#include +#include +#include +#include + +#include + + +namespace QmlDesigner { + +class PixmapItem : public QObject, public QGraphicsPixmapItem +{ + Q_OBJECT + Q_PROPERTY(QPointF pos READ pos WRITE setPos) +public: + PixmapItem(const QPixmap &pix) : QGraphicsPixmapItem(pix) { } +}; + +class EasingSimulation : public QObject +{ + Q_OBJECT +public: + EasingSimulation(QObject *parent=0, int length=210):QObject(parent) { + m_qtLogo = new PixmapItem(QPixmap(":/qt_logo.png")); + m_scene.addItem(m_qtLogo); + m_scene.setSceneRect(0,0,length,m_qtLogo->boundingRect().height()); + m_qtLogo->hide(); + m_sequential = 0; + } + + ~EasingSimulation() { delete m_qtLogo; } + + QGraphicsScene *scene() { return &m_scene; } + void show() { m_qtLogo->show(); } + void hide() { m_qtLogo->hide(); } + void reset() { m_qtLogo->setPos(0,0); } + void stop() { + if (m_sequential) { + m_sequential->stop(); + reset(); + emit finished(); + } + } + bool running() { + if (m_sequential) + return m_sequential->state()==QAbstractAnimation::Running; + else + return false; + } + void updateCurve(QEasingCurve newCurve, int newDuration) { + if (running()) { + m_sequential->pause(); + static_cast(m_sequential->animationAt(1))->setEasingCurve(newCurve); + static_cast(m_sequential->animationAt(1))->setDuration(newDuration); + m_sequential->resume(); + } + } + void animate(int duration, QEasingCurve curve) { + reset(); + m_sequential = new QSequentialAnimationGroup; + connect(m_sequential,SIGNAL(finished()),this,SIGNAL(finished())); + m_sequential->addPause(150); + QPropertyAnimation *m_anim = new QPropertyAnimation (m_qtLogo, "pos"); + m_anim->setStartValue(QPointF(0, 0)); + m_anim->setEndValue(QPointF(m_scene.sceneRect().width() - m_qtLogo->boundingRect().width(), 0)); + m_anim->setDuration(duration); + m_anim->setEasingCurve(curve); + m_sequential->addAnimation(m_anim); + m_sequential->addPause(300); + m_sequential->start(); + } + +signals: + void finished(); + +private: + PixmapItem *m_qtLogo; + QGraphicsScene m_scene; + QSequentialAnimationGroup *m_sequential; +}; + + +EasingContextPane::EasingContextPane(QWidget *parent) : + QWidget(parent), + ui(new Ui::EasingContextPane) +{ + ui->setupUi(this); + + m_simulation = new EasingSimulation(this, 210); + ui->graphicsView->setScene(m_simulation->scene()); + + m_easingGraph = new EasingGraph(this); + m_easingGraph->raise(); + setLinear(); + + ui->playButton->setIcon(QIcon(":/playicon.png")); + + + + setGraphDisplayMode(GraphMode); + + connect(m_simulation,SIGNAL(finished()),this,SLOT(switchToGraph())); +} + +EasingContextPane::~EasingContextPane() +{ + delete ui; +} + + +bool EasingContextPane::acceptsType(const QString &typeName) +{ + return typeName.contains("NumberAnimation") || + typeName.contains("PropertyAnimation") || + typeName.contains("ColorAnimation") || + typeName.contains("RotationAnimation"); +} + +void EasingContextPane::setProperties(QmlJS::PropertyReader *propertyReader) +{ + m_easingGraph->setGeometry(ui->graphicsView->geometry().adjusted(2,2,-2,-2)); + QString newEasingType = QString("Linear"); + if (propertyReader->hasProperty(QLatin1String("easing.type"))) { + newEasingType = propertyReader->readProperty(QLatin1String("easing.type")).toString(); + if (newEasingType.contains(".")) + newEasingType = newEasingType.right(newEasingType.length() - newEasingType.indexOf(".") - 1); + } + + m_easingGraph->setEasingName(newEasingType); + ui->easingShapeComboBox->setCurrentIndex(ui->easingShapeComboBox->findText(m_easingGraph->easingShape())); + ui->easingExtremesComboBox->setCurrentIndex(ui->easingExtremesComboBox->findText(m_easingGraph->easingExtremes())); + + + if (propertyReader->hasProperty(QLatin1String("easing.period"))) { + qreal period = propertyReader->readProperty(QLatin1String("easing.period")).toDouble(); + if (period < ui->periodSpinBox->minimum() || period > ui->periodSpinBox->maximum()) + ui->periodSpinBox->setValue(ui->periodSpinBox->minimum()); + else + ui->periodSpinBox->setValue(period); + } + else + ui->periodSpinBox->setValue(0.3); + + if (propertyReader->hasProperty(QLatin1String("easing.amplitude"))) { + qreal amplitude = propertyReader->readProperty(QLatin1String("easing.amplitude")).toDouble(); + if (amplitude < ui->amplitudeSpinBox->minimum() || amplitude > ui->amplitudeSpinBox->maximum()) + ui->amplitudeSpinBox->setValue(ui->amplitudeSpinBox->minimum()); + else + ui->amplitudeSpinBox->setValue(amplitude); + } + else + ui->amplitudeSpinBox->setValue(1.0); + + if (propertyReader->hasProperty(QLatin1String("easing.overshoot"))) { + qreal overshoot = propertyReader->readProperty(QLatin1String("easing.overshoot")).toDouble(); + if (overshoot < ui->overshootSpinBox->minimum() || overshoot > ui->overshootSpinBox->maximum()) + ui->overshootSpinBox->setValue(ui->overshootSpinBox->minimum()); + else + ui->overshootSpinBox->setValue(overshoot); + } + else + ui->overshootSpinBox->setValue(1.70158); + + if (propertyReader->hasProperty(QLatin1String("duration"))) { + qreal duration = propertyReader->readProperty(QLatin1String("duration")).toInt(); + if (duration < ui->durationSpinBox->minimum() || duration > ui->durationSpinBox->maximum()) + ui->durationSpinBox->setValue(ui->durationSpinBox->minimum()); + else + ui->durationSpinBox->setValue(duration); + } + else + ui->durationSpinBox->setValue(250); +} + +void EasingContextPane::changeEvent(QEvent *e) +{ + QWidget::changeEvent(e); + switch (e->type()) { + case QEvent::LanguageChange: + ui->retranslateUi(this); + break; + default: + break; + } +} + +void EasingContextPane::setGraphDisplayMode(GraphDisplayMode newMode) +{ + m_displayMode = newMode; + switch (newMode) { + case GraphMode: { +// ui->graphSelectButton->setIcon(QIcon(":/simulicon.png")); + m_simulation->hide(); + m_easingGraph->show(); + break; + } + case SimulationMode: { +// ui->graphSelectButton->setIcon(QIcon(":/graphicon.png")); + m_simulation->show(); + m_easingGraph->hide(); + break; + } + default: break; + } + +} + +void EasingContextPane::startAnimation() +{ + if (m_simulation->running()) + m_simulation->stop(); + else { + m_simulation->animate(ui->durationSpinBox->value(), m_easingGraph->easingCurve()); + ui->playButton->setIcon(QIcon(":/stopicon.png")); + } + +} + +void EasingContextPane::switchToGraph() +{ + ui->playButton->setIcon(QIcon(":/playicon.png")); + setGraphDisplayMode(GraphMode); +} + +void EasingContextPane::setOthers() +{ + ui->easingExtremesComboBox->setEnabled(true); + ui->amplitudeSpinBox->setEnabled(false); + ui->overshootSpinBox->setEnabled(false); + ui->overshootSpinBox->setEnabled(false); + ui->periodSpinBox->setEnabled(false); + +// ui->durationSpinBox->setSuffix(" ms"); +// ui->durationSpinBox->setGeometry(0,65,90,23); +// ui->easingExtremesComboBox->setGeometry(90,64,75,25); +// ui->easingShapeComboBox->setGeometry(165,64,115,25); +// ui->easingExtremesComboBox->show(); +// ui->amplitudeSpinBox->hide(); +// ui->periodSpinBox->hide(); +// ui->overshootSpinBox->hide(); +} + +void EasingContextPane::setLinear() +{ + ui->easingExtremesComboBox->setEnabled(false); + ui->amplitudeSpinBox->setEnabled(false); + ui->overshootSpinBox->setEnabled(false); + ui->periodSpinBox->setEnabled(false); +} + +void EasingContextPane::setBack() +{ + ui->easingExtremesComboBox->setEnabled(true); + ui->amplitudeSpinBox->setEnabled(false); + ui->overshootSpinBox->setEnabled(true); + ui->periodSpinBox->setEnabled(false); +} + +void EasingContextPane::setElastic() +{ + ui->easingExtremesComboBox->setEnabled(true); + ui->amplitudeSpinBox->setEnabled(true); + ui->overshootSpinBox->setEnabled(false); + ui->periodSpinBox->setEnabled(true); +} + +void EasingContextPane::setBounce() +{ + ui->easingExtremesComboBox->setEnabled(true); + ui->amplitudeSpinBox->setEnabled(true); + ui->overshootSpinBox->setEnabled(false); + ui->periodSpinBox->setEnabled(false); +} + +} //QmlDesigner + +void QmlDesigner::EasingContextPane::on_durationSpinBox_valueChanged(int newValue) +{ + m_simulation->updateCurve(m_easingGraph->easingCurve(),ui->durationSpinBox->value()); + emit propertyChanged(QLatin1String("duration"), newValue); +} + +void QmlDesigner::EasingContextPane::on_easingShapeComboBox_currentIndexChanged(QString newShape) +{ + if (newShape=="Linear") + setLinear(); + else if (newShape=="Bounce") + setBounce(); + else if (newShape=="Elastic") + setElastic(); + else if (newShape=="Back") + setBack(); + else + setOthers(); + + if (m_easingGraph->easingShape() != newShape) { + m_easingGraph->setEasingShape(newShape); + // reload easing parameters + m_easingGraph->setAmplitude(ui->amplitudeSpinBox->value()); + m_easingGraph->setPeriod(ui->periodSpinBox->value()); + m_easingGraph->setOvershoot(ui->overshootSpinBox->value()); + m_simulation->updateCurve(m_easingGraph->easingCurve(),ui->durationSpinBox->value()); + emit propertyChanged(QLatin1String("easing.type"), QVariant(QLatin1String("Easing.")+m_easingGraph->easingName())); + } +} + +void QmlDesigner::EasingContextPane::on_easingExtremesComboBox_currentIndexChanged(QString newExtremes) +{ + if (m_easingGraph->easingExtremes() != newExtremes) { + m_easingGraph->setEasingExtremes(newExtremes); + m_easingGraph->setAmplitude(ui->amplitudeSpinBox->value()); + m_easingGraph->setPeriod(ui->periodSpinBox->value()); + m_easingGraph->setOvershoot(ui->overshootSpinBox->value()); + m_simulation->updateCurve(m_easingGraph->easingCurve(),ui->durationSpinBox->value()); + emit propertyChanged(QLatin1String("easing.type"), QVariant(QLatin1String("Easing.")+m_easingGraph->easingName())); + } +} + +void QmlDesigner::EasingContextPane::on_amplitudeSpinBox_valueChanged(double newAmplitude) +{ + if ((newAmplitude != m_easingGraph->amplitude()) && + (m_easingGraph->easingShape()=="Bounce" || m_easingGraph->easingShape()=="Elastic")) { + m_easingGraph->setAmplitude(newAmplitude); + m_simulation->updateCurve(m_easingGraph->easingCurve(),ui->durationSpinBox->value()); + emit propertyChanged(QLatin1String("easing.amplitude"), newAmplitude); + } +} + +void QmlDesigner::EasingContextPane::on_periodSpinBox_valueChanged(double newPeriod) +{ + if ((newPeriod != m_easingGraph->period()) && (m_easingGraph->easingShape()=="Elastic")) { + m_easingGraph->setPeriod(newPeriod); + m_simulation->updateCurve(m_easingGraph->easingCurve(),ui->durationSpinBox->value()); + emit propertyChanged(QLatin1String("easing.period"), newPeriod); + } + +} + +void QmlDesigner::EasingContextPane::on_overshootSpinBox_valueChanged(double newOvershoot) +{ + if ((newOvershoot != m_easingGraph->overshoot()) && (m_easingGraph->easingShape()=="Back")) { + m_easingGraph->setOvershoot(newOvershoot); + m_simulation->updateCurve(m_easingGraph->easingCurve(),ui->durationSpinBox->value()); + emit propertyChanged(QLatin1String("easing.overshoot"), newOvershoot); + } +} + +void QmlDesigner::EasingContextPane::on_graphSelectButton_clicked() +{ + setGraphDisplayMode(m_displayMode==GraphMode?SimulationMode:GraphMode); +} + +void QmlDesigner::EasingContextPane::on_playButton_clicked() +{ + setGraphDisplayMode(SimulationMode); + startAnimation(); +} + +#include "easingcontextpane.moc" diff --git a/src/plugins/qmldesigner/components/easingpane/easingcontextpane.h b/src/plugins/qmldesigner/components/easingpane/easingcontextpane.h new file mode 100644 index 00000000000..c12661882e5 --- /dev/null +++ b/src/plugins/qmldesigner/components/easingpane/easingcontextpane.h @@ -0,0 +1,73 @@ +#ifndef EASINGCONTEXTPANE_H +#define EASINGCONTEXTPANE_H + +#include +#include + +#include "easinggraph.h" + + +QT_BEGIN_NAMESPACE +namespace Ui { + class EasingContextPane; +} +QT_END_NAMESPACE + +namespace QmlJS { + class PropertyReader; +} + +namespace QmlDesigner { +class EasingSimulation; + +class EasingContextPane : public QWidget +{ + Q_OBJECT + + enum GraphDisplayMode { GraphMode, SimulationMode }; +public: + explicit EasingContextPane(QWidget *parent = 0); + ~EasingContextPane(); + + void setProperties(QmlJS::PropertyReader *propertyReader); + void setGraphDisplayMode(GraphDisplayMode newMode); + void startAnimation(); + + bool acceptsType(const QString &); + +signals: + void propertyChanged(const QString &, const QVariant &); + void removeProperty(const QString &); + void removeAndChangeProperty(const QString &, const QString &, const QVariant &); + +protected: + void changeEvent(QEvent *e); + + void setOthers(); + void setLinear(); + void setBack(); + void setElastic(); + void setBounce(); + +private: + Ui::EasingContextPane *ui; + GraphDisplayMode m_displayMode; + EasingGraph *m_easingGraph; + EasingSimulation *m_simulation; + +private slots: + + void on_playButton_clicked(); + void on_graphSelectButton_clicked(); + void on_overshootSpinBox_valueChanged(double ); + void on_periodSpinBox_valueChanged(double ); + void on_amplitudeSpinBox_valueChanged(double ); + void on_easingExtremesComboBox_currentIndexChanged(QString ); + void on_easingShapeComboBox_currentIndexChanged(QString ); + void on_durationSpinBox_valueChanged(int ); + + void switchToGraph(); +}; + +} +#endif // EASINGCONTEXTPANE_H diff --git a/src/plugins/qmldesigner/components/easingpane/easingcontextpane.ui b/src/plugins/qmldesigner/components/easingpane/easingcontextpane.ui new file mode 100644 index 00000000000..a01395e9c84 --- /dev/null +++ b/src/plugins/qmldesigner/components/easingpane/easingcontextpane.ui @@ -0,0 +1,341 @@ + + + EasingContextPane + + + + 0 + 0 + 260 + 165 + + + + Dialog + + + + 3 + + + 3 + + + + + true + + + false + + + + + + + + 0 + 83 + + + + + 30 + 16777215 + + + + play simulation + + + + + + + Easing + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + + 70 + 16777215 + + + + easing type + + + + Linear + + + + + Quad + + + + + Cubic + + + + + Quart + + + + + Quint + + + + + Sine + + + + + Expo + + + + + Circ + + + + + Elastic + + + + + Back + + + + + Bounce + + + + + + + + Qt::LeftToRight + + + Subtype + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + easing subtype + + + + In + + + + + Out + + + + + InOut + + + + + OutIn + + + + + + + + Duration + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 70 + 16777215 + + + + duration + + + INVALID + + + ms + + + 0 + + + 9999999 + + + 10 + + + 250 + + + + + + + Amplitude + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 70 + 16777215 + + + + easing amplitude (only for Elastic and Bounce curves) + + + INVALID + + + 3 + + + 999999.989999999990687 + + + 0.050000000000000 + + + 1.000000000000000 + + + + + + + Period + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 70 + 16777215 + + + + easing period (only for Elastic curve) + + + INVALID + + + 3 + + + 999999.989999999990687 + + + 0.010000000000000 + + + 0.300000000000000 + + + + + + + Overshoot + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 70 + 16777215 + + + + easing overshoot (only for Back curve) + + + INVALID + + + 3 + + + 999999.989999999990687 + + + 0.050000000000000 + + + 1.700000000000000 + + + + + + + + diff --git a/src/plugins/qmldesigner/components/easingpane/easinggraph.cpp b/src/plugins/qmldesigner/components/easingpane/easinggraph.cpp new file mode 100644 index 00000000000..25f53999539 --- /dev/null +++ b/src/plugins/qmldesigner/components/easingpane/easinggraph.cpp @@ -0,0 +1,288 @@ +#include "easinggraph.h" + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +EasingGraph::EasingGraph(QWidget *parent):QWidget(parent) +{ +// setFlag(QGraphicsItem::ItemHasNoContents, false); + + // populate the hash + m_availableNames["Linear"]=QEasingCurve::Linear; + m_availableNames["InQuad"]=QEasingCurve::InQuad; + m_availableNames["OutQuad"]=QEasingCurve::OutQuad; + m_availableNames["InOutQuad"]=QEasingCurve::InOutQuad; + m_availableNames["OutInQuad"]=QEasingCurve::OutInQuad; + m_availableNames["InCubic"]=QEasingCurve::InCubic; + m_availableNames["OutCubic"]=QEasingCurve::OutCubic; + m_availableNames["InOutCubic"]=QEasingCurve::InOutCubic; + m_availableNames["OutInCubic"]=QEasingCurve::OutInCubic; + m_availableNames["InQuart"]=QEasingCurve::InQuart; + m_availableNames["OutQuart"]=QEasingCurve::OutQuart; + m_availableNames["InOutQuart"]=QEasingCurve::InOutQuart; + m_availableNames["OutInQuart"]=QEasingCurve::OutInQuart; + m_availableNames["InQuint"]=QEasingCurve::InQuint; + m_availableNames["OutQuint"]=QEasingCurve::OutQuint; + m_availableNames["InOutQuint"]=QEasingCurve::InOutQuint; + m_availableNames["OutInQuint"]=QEasingCurve::OutInQuint; + m_availableNames["InSine"]=QEasingCurve::InSine; + m_availableNames["OutSine"]=QEasingCurve::OutSine; + m_availableNames["InOutSine"]=QEasingCurve::InOutSine; + m_availableNames["OutInSine"]=QEasingCurve::OutInSine; + m_availableNames["InExpo"]=QEasingCurve::InExpo; + m_availableNames["OutExpo"]=QEasingCurve::OutExpo; + m_availableNames["InOutExpo"]=QEasingCurve::InOutExpo; + m_availableNames["OutInExpo"]=QEasingCurve::OutInExpo; + m_availableNames["InCirc"]=QEasingCurve::InCirc; + m_availableNames["OutCirc"]=QEasingCurve::OutCirc; + m_availableNames["InOutCirc"]=QEasingCurve::InOutCirc; + m_availableNames["OutInCirc"]=QEasingCurve::OutInCirc; + m_availableNames["InElastic"]=QEasingCurve::InElastic; + m_availableNames["OutElastic"]=QEasingCurve::OutElastic; + m_availableNames["InOutElastic"]=QEasingCurve::InOutElastic; + m_availableNames["OutInElastic"]=QEasingCurve::OutInElastic; + m_availableNames["InBack"]=QEasingCurve::InBack; + m_availableNames["OutBack"]=QEasingCurve::OutBack; + m_availableNames["InOutBack"]=QEasingCurve::InOutBack; + m_availableNames["OutInBack"]=QEasingCurve::OutInBack; + m_availableNames["InBounce"]=QEasingCurve::InBounce; + m_availableNames["OutBounce"]=QEasingCurve::OutBounce; + m_availableNames["InOutBounce"]=QEasingCurve::InOutBounce; + m_availableNames["OutInBounce"]=QEasingCurve::OutInBounce; + m_availableNames["InCurve"]=QEasingCurve::InCurve; + m_availableNames["OutCurve"]=QEasingCurve::OutCurve; + m_availableNames["SineCurve"]=QEasingCurve::SineCurve; + m_availableNames["CosineCurve"]=QEasingCurve::CosineCurve; + + m_color = Qt::magenta; + m_zeroColor = Qt::gray; + m_easingExtremes = "In"; +} + + +EasingGraph::~EasingGraph() +{ +} + +QEasingCurve::Type EasingGraph::easingType() const +{ + return m_curveFunction.type(); +} + +QEasingCurve EasingGraph::easingCurve() const +{ + return m_curveFunction; +} + +QString EasingGraph::easingShape() const +{ + QString name = easingName(); + if (name.left(5)=="InOut") return name.right(name.length()-5); + if (name.left(5)=="OutIn") return name.right(name.length()-5); + if (name.left(3)=="Out") return name.right(name.length()-3); + if (name.left(2)=="In") return name.right(name.length()-2); + return name; +} + +void EasingGraph::setEasingShape(const QString &newShape) +{ + if (easingShape() != newShape) { + if (newShape=="Linear") + setEasingName(newShape); + else + setEasingName(m_easingExtremes+newShape); + } +} + +QString EasingGraph::easingExtremes() const +{ + QString name = easingName(); + if (name.left(5)=="InOut") return "InOut"; + if (name.left(5)=="OutIn") return "OutIn"; + if (name.left(3)=="Out") return "Out"; + if (name.left(2)=="In") return "In"; + return QString(); +} + +void EasingGraph::setEasingExtremes(const QString &newExtremes) +{ + if (m_easingExtremes != newExtremes) { + m_easingExtremes = newExtremes; + if (easingShape()!="Linear") + setEasingName(newExtremes+easingShape()); + } +} + +QString EasingGraph::easingName() const +{ + return m_availableNames.key(m_curveFunction.type()); +} + +void EasingGraph::setEasingName(const QString &newName) +{ + if (easingName() != newName) { + + if (!m_availableNames.contains(newName)) return; + m_curveFunction = QEasingCurve(m_availableNames.value(newName)); + emit easingNameChanged(); + emit easingExtremesChanged(); + emit easingShapeChanged(); + update(); + } +} + +qreal EasingGraph::overshoot() const +{ + return m_curveFunction.overshoot(); +} + +void EasingGraph::setOvershoot(qreal newOvershoot) +{ + if ((overshoot() != newOvershoot) && (easingShape()=="Back")) { + m_curveFunction.setOvershoot(newOvershoot); + emit overshootChanged(); + update(); + } +} +qreal EasingGraph::amplitude() const +{ + return m_curveFunction.amplitude(); +} + +void EasingGraph::setAmplitude(qreal newAmplitude) +{ + if ((amplitude() != newAmplitude) && ((easingShape()=="Bounce") ||(easingShape()=="Elastic"))) { + m_curveFunction.setAmplitude(newAmplitude); + emit amplitudeChanged(); + update(); + } +} + +qreal EasingGraph::period() const +{ + return m_curveFunction.period(); +} + +void EasingGraph::setPeriod(qreal newPeriod) +{ + if ((period() != newPeriod) && (easingShape()=="Elastic")) { + m_curveFunction.setPeriod(newPeriod); + emit periodChanged(); + update(); + } +} + +qreal EasingGraph::duration() const +{ + return m_duration; +} + +void EasingGraph::setDuration(qreal newDuration) +{ + if (m_duration != newDuration) { + m_duration = newDuration; + emit durationChanged(); + } +} + +QColor EasingGraph::color() const +{ + return m_color; +} + +void EasingGraph::setColor(const QColor &newColor) +{ + if (m_color != newColor) { + m_color = newColor; + emit colorChanged(); + update(); + } +} + +QColor EasingGraph::zeroColor() const{ + return m_zeroColor; +} + +void EasingGraph::setZeroColor(const QColor &newColor) +{ + if (m_zeroColor != newColor) { + m_zeroColor = newColor; + emit zeroColorChanged(); + update(); + } +} + +QRectF EasingGraph::boundingRect() const +{ + return QRectF(0, 0, width(), height()); +} + +void EasingGraph::paintEvent(QPaintEvent *event) +//void EasingGraph::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) +{ + QWidget::paintEvent(event); + + QPainter *painter = new QPainter(this); + painter->save(); + bool drawZero = false; + + // no background + + int length = width(); + int breadth = height()-2; + QPainterPath path; + path.moveTo(0,int((1-m_curveFunction.valueForProgress(0))*breadth)); + for (int i=0;ibreadth)) { + // scale vertically + qreal scale = breadth/pathRect.height(); + qreal displacement = -pathRect.top(); + + // reset path and recompute scaled version + path = QPainterPath(); + path.moveTo(0,int(scale*((1-m_curveFunction.valueForProgress(0))*breadth+displacement))); + for (int i=0;isetBrush(Qt::transparent); + + if (drawZero) { + // "zero" and "one" lines + QPen zeroPen = QPen(m_zeroColor); + zeroPen.setStyle(Qt::DashLine); + painter->setPen(zeroPen); + int y = int(-pathRect.top()*breadth/pathRect.height()); + if (y>0) + painter->drawLine(0,y,length,y); + y = int(breadth/pathRect.height()*(breadth-pathRect.top())); + if (ydrawLine(0,y,length,y); + } + + painter->setPen(m_color); + painter->drawPath(path); + painter->restore(); + delete painter; +} + +QT_END_NAMESPACE diff --git a/src/plugins/qmldesigner/components/easingpane/easinggraph.h b/src/plugins/qmldesigner/components/easingpane/easinggraph.h new file mode 100644 index 00000000000..22387ffb632 --- /dev/null +++ b/src/plugins/qmldesigner/components/easingpane/easinggraph.h @@ -0,0 +1,91 @@ +#ifndef EASINGGRAPH_H +#define EASINGGRAPH_H + +//#include +#include +#include +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) + + +class EasingGraph: public QWidget +{ + Q_OBJECT + + Q_PROPERTY (QString easingShape READ easingShape WRITE setEasingShape NOTIFY easingShapeChanged) + Q_PROPERTY (QString easingExtremes READ easingExtremes WRITE setEasingExtremes NOTIFY easingExtremesChanged) + Q_PROPERTY (QString easingName READ easingName WRITE setEasingName NOTIFY easingNameChanged) + Q_PROPERTY (qreal overshoot READ overshoot WRITE setOvershoot NOTIFY overshootChanged) + Q_PROPERTY (qreal amplitude READ amplitude WRITE setAmplitude NOTIFY amplitudeChanged) + Q_PROPERTY (qreal period READ period WRITE setPeriod NOTIFY periodChanged) + Q_PROPERTY (qreal duration READ duration WRITE setDuration NOTIFY durationChanged) + Q_PROPERTY (QColor color READ color WRITE setColor NOTIFY colorChanged) + Q_PROPERTY (QColor zeroColor READ zeroColor WRITE setZeroColor NOTIFY zeroColorChanged) + +public: + EasingGraph(QWidget *parent=0); + ~EasingGraph(); + + QEasingCurve::Type easingType() const; + QEasingCurve easingCurve() const; + + QString easingShape() const; + void setEasingShape(const QString &newShape); + QString easingExtremes() const; + void setEasingExtremes(const QString &newExtremes); + QString easingName() const; + void setEasingName(const QString &newName); + qreal overshoot() const; + void setOvershoot(qreal newOvershoot); + qreal amplitude() const; + void setAmplitude(qreal newAmplitude); + qreal period() const; + void setPeriod(qreal newPeriod); + qreal duration() const; + void setDuration(qreal newDuration); + + QColor color() const; + void setColor(const QColor &newColor); + QColor zeroColor() const; + void setZeroColor(const QColor &newColor); + + QRectF boundingRect() const; + //void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *); + void paintEvent(QPaintEvent *); + +signals: + void easingShapeChanged(); + void easingExtremesChanged(); + void easingNameChanged(); + void overshootChanged(); + void amplitudeChanged(); + void durationChanged(); + void periodChanged(); + void colorChanged(); + void zeroColorChanged(); + +private: + Q_DISABLE_COPY(EasingGraph) + + QColor m_color; + QColor m_zeroColor; // the color for the "zero" and "one" lines + qreal m_duration; + + QString m_easingExtremes; + + QEasingCurve m_curveFunction; + QHash m_availableNames; +}; + +QT_END_NAMESPACE + +//QML_DECLARE_TYPE(EasingGraph) + +QT_END_HEADER + +#endif // EASINGGRAPH_H diff --git a/src/plugins/qmldesigner/components/easingpane/easingpane.pri b/src/plugins/qmldesigner/components/easingpane/easingpane.pri new file mode 100644 index 00000000000..31e8b07f23e --- /dev/null +++ b/src/plugins/qmldesigner/components/easingpane/easingpane.pri @@ -0,0 +1,12 @@ +VPATH += $$PWD +INCLUDEPATH += $$PWD +#include($$PWD/qtgradienteditor/qtgradienteditor.pri) +SOURCES += easinggraph.cpp \ + easingcontextpane.cpp + +HEADERS += easinggraph.h \ + easingcontextpane.h + +QT += declarative +RESOURCES += easingpane.qrc +FORMS += components/easingpane/easingcontextpane.ui diff --git a/src/plugins/qmldesigner/components/easingpane/easingpane.qrc b/src/plugins/qmldesigner/components/easingpane/easingpane.qrc new file mode 100644 index 00000000000..f6e69536806 --- /dev/null +++ b/src/plugins/qmldesigner/components/easingpane/easingpane.qrc @@ -0,0 +1,7 @@ + + + qt_logo.png + playicon.png + stopicon.png + + diff --git a/src/plugins/qmldesigner/components/easingpane/playicon.png b/src/plugins/qmldesigner/components/easingpane/playicon.png new file mode 100644 index 00000000000..27fe8239610 Binary files /dev/null and b/src/plugins/qmldesigner/components/easingpane/playicon.png differ diff --git a/src/plugins/qmldesigner/components/easingpane/qt_logo.png b/src/plugins/qmldesigner/components/easingpane/qt_logo.png new file mode 100644 index 00000000000..3cbfca726ba Binary files /dev/null and b/src/plugins/qmldesigner/components/easingpane/qt_logo.png differ diff --git a/src/plugins/qmldesigner/components/easingpane/stopicon.png b/src/plugins/qmldesigner/components/easingpane/stopicon.png new file mode 100644 index 00000000000..6e5e6eead96 Binary files /dev/null and b/src/plugins/qmldesigner/components/easingpane/stopicon.png differ diff --git a/src/plugins/qmldesigner/components/propertyeditor/contextpanewidget.cpp b/src/plugins/qmldesigner/components/propertyeditor/contextpanewidget.cpp index 24be83bada5..27af5c3b28e 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/contextpanewidget.cpp +++ b/src/plugins/qmldesigner/components/propertyeditor/contextpanewidget.cpp @@ -14,10 +14,10 @@ #include #include "colorwidget.h" #include "contextpanetextwidget.h" +#include "easingcontextpane.h" #include "contextpanewidgetimage.h" #include "contextpanewidgetrectangle.h" - namespace QmlDesigner { ContextPaneWidget::ContextPaneWidget(QWidget *parent) : QFrame(parent), m_currentWidget(0), m_xPos(-1) @@ -48,9 +48,12 @@ ContextPaneWidget::ContextPaneWidget(QWidget *parent) : QFrame(parent), m_curren m_currentWidget = fontWidget; QWidget *imageWidget = createImageWidget(); QWidget *rectangleWidget = createRectangleWidget(); + QWidget *easingWidget = createEasingWidget(); layout->addWidget(fontWidget, 0, 1, 2, 1); + layout->addWidget(easingWidget, 0, 1, 2, 1); layout->addWidget(imageWidget, 0, 1, 2, 1); layout->addWidget(rectangleWidget, 0, 1, 2, 1); + setAutoFillBackground(true); setContextMenuPolicy(Qt::ActionsContextMenu); @@ -117,6 +120,10 @@ void ContextPaneWidget::setProperties(::QmlJS::PropertyReader *propertyReader) if (textWidget) textWidget->setProperties(propertyReader); + EasingContextPane *easingWidget = qobject_cast(m_currentWidget); + if (easingWidget) + easingWidget->setProperties(propertyReader); + ContextPaneWidgetImage *imageWidget = qobject_cast(m_currentWidget); if (imageWidget) imageWidget->setProperties(propertyReader); @@ -139,6 +146,7 @@ bool ContextPaneWidget::setType(const QString &typeName) m_imageWidget->hide(); m_textWidget->hide(); m_rectangleWidget->hide(); + m_easingWidget->hide(); if (typeName.contains("Text")) { m_currentWidget = m_textWidget; @@ -153,6 +161,12 @@ bool ContextPaneWidget::setType(const QString &typeName) } return true; } + + if (m_easingWidget->acceptsType(typeName)) { + m_currentWidget = m_easingWidget; + m_easingWidget->show(); + return true; + } if (typeName.contains("Rectangle")) { m_currentWidget = m_rectangleWidget; m_rectangleWidget->show(); @@ -163,10 +177,15 @@ bool ContextPaneWidget::setType(const QString &typeName) m_imageWidget->show(); return true; } - return false; } +bool ContextPaneWidget::acceptsType(const QString &typeName) +{ + return typeName.contains("Text") || m_easingWidget->acceptsType(typeName) || + typeName.contains("Rectangle") || typeName.contains("Image"); +} + void ContextPaneWidget::onTogglePane() { if (!m_currentWidget) @@ -257,6 +276,17 @@ QWidget* ContextPaneWidget::createFontWidget() return m_textWidget; } +QWidget* ContextPaneWidget::createEasingWidget() +{ + m_easingWidget = new EasingContextPane(this); + + connect(m_easingWidget, SIGNAL(propertyChanged(QString,QVariant)), this, SIGNAL(propertyChanged(QString,QVariant))); + connect(m_easingWidget, SIGNAL(removeProperty(QString)), this, SIGNAL(removeProperty(QString))); + connect(m_easingWidget, SIGNAL(removeAndChangeProperty(QString,QString,QVariant)), this, SIGNAL(removeAndChangeProperty(QString,QString,QVariant))); + + return m_easingWidget; +} + QWidget *ContextPaneWidget::createImageWidget() { m_imageWidget = new ContextPaneWidgetImage(this); @@ -278,7 +308,6 @@ QWidget *ContextPaneWidget::createRectangleWidget() } - } //QmlDesigner diff --git a/src/plugins/qmldesigner/components/propertyeditor/contextpanewidget.h b/src/plugins/qmldesigner/components/propertyeditor/contextpanewidget.h index d896ed4d610..dfd87fe108e 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/contextpanewidget.h +++ b/src/plugins/qmldesigner/components/propertyeditor/contextpanewidget.h @@ -14,6 +14,7 @@ namespace QmlDesigner { class BauhausColorDialog; class ContextPaneTextWidget; +class EasingContextPane; class ContextPaneWidgetRectangle; class ContextPaneWidgetImage; @@ -31,6 +32,7 @@ public: void setProperties(QmlJS::PropertyReader *propertyReader); void setPath(const QString &path); bool setType(const QString &typeName); + bool acceptsType(const QString &typeName); QWidget* currentWidget() const { return m_currentWidget; } public slots: @@ -48,8 +50,10 @@ private slots: protected: QWidget *createFontWidget(); + QWidget *createEasingWidget(); QWidget *createImageWidget(); QWidget *createRectangleWidget(); + void mousePressEvent(QMouseEvent * event); void mouseReleaseEvent(QMouseEvent * event); void mouseMoveEvent(QMouseEvent * event); @@ -57,6 +61,7 @@ protected: private: QWidget *m_currentWidget; ContextPaneTextWidget *m_textWidget; + EasingContextPane *m_easingWidget; ContextPaneWidgetImage *m_imageWidget; ContextPaneWidgetRectangle *m_rectangleWidget; QPoint m_oldPos; diff --git a/src/plugins/qmldesigner/qmlcontextpane.cpp b/src/plugins/qmldesigner/qmlcontextpane.cpp index 52defaba5d0..dbad104c219 100644 --- a/src/plugins/qmldesigner/qmlcontextpane.cpp +++ b/src/plugins/qmldesigner/qmlcontextpane.cpp @@ -32,7 +32,7 @@ static inline QString textAt(const Document* doc, QmlContextPane::QmlContextPane(QObject *parent) : ::QmlJS::IContextPane(parent), m_blockWriting(false) { m_node = 0; - ContextPaneWidget(); + contextWidget(); m_propertyOrder << QLatin1String("id") @@ -130,7 +130,7 @@ void QmlContextPane::apply(TextEditor::BaseTextEditorEditable *editor, Document: rect.moveTo(reg.boundingRect().topLeft()); reg = reg.intersect(rect); - if (name.contains("Text") || name.contains("Rectangle") || name.contains("Image")) { + if (contextWidget()->acceptsType(name)) { m_node = 0; PropertyReader propertyReader(doc, initializer); QTextCursor tc(editor->editor()->document()); @@ -148,6 +148,7 @@ void QmlContextPane::apply(TextEditor::BaseTextEditorEditable *editor, Document: contextWidget()->activate(p3 , p1, p2); else contextWidget()->rePosition(p3 , p1, p2); + m_blockWriting = true; contextWidget()->setPath(doc->path()); contextWidget()->setProperties(&propertyReader); diff --git a/src/plugins/qmldesigner/qmldesignerplugin.pro b/src/plugins/qmldesigner/qmldesignerplugin.pro index e3d5d487e7d..c3cd8518e8c 100644 --- a/src/plugins/qmldesigner/qmldesignerplugin.pro +++ b/src/plugins/qmldesigner/qmldesignerplugin.pro @@ -15,6 +15,7 @@ include(components/pluginmanager/pluginmanager.pri) include(components/themeloader/qts60stylethemeio.pri) include(components/stateseditor/stateseditor.pri) include(components/resources/resources.pri) +include(components/easingpane/easingpane.pri) HEADERS += qmldesignerconstants.h \ qmldesignerplugin.h \