QmlDesigner.EasingPane: Adding

Introducing context pane for selecting easing curves in animations.
Reviewed by: Thomas Hartmann
This commit is contained in:
Christiaan Janssen
2010-07-19 12:06:40 +02:00
parent 3961676569
commit 6153769cd8
14 changed files with 1216 additions and 5 deletions

View File

@@ -0,0 +1,363 @@
#include "easingcontextpane.h"
#include "ui_easingcontextpane.h"
#include <qmljs/qmljspropertyreader.h>
#include <QGraphicsPixmapItem>
#include <QGraphicsScene>
#include <QPropertyAnimation>
#include <QSequentialAnimationGroup>
#include <qdebug.h>
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<QPropertyAnimation *>(m_sequential->animationAt(1))->setEasingCurve(newCurve);
static_cast<QPropertyAnimation *>(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"

View File

@@ -0,0 +1,73 @@
#ifndef EASINGCONTEXTPANE_H
#define EASINGCONTEXTPANE_H
#include <QWidget>
#include <QVariant>
#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

View File

@@ -0,0 +1,341 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>EasingContextPane</class>
<widget class="QWidget" name="EasingContextPane">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>260</width>
<height>165</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="margin">
<number>3</number>
</property>
<property name="spacing">
<number>3</number>
</property>
<item row="0" column="0" colspan="4">
<widget class="QGraphicsView" name="graphicsView">
<property name="enabled">
<bool>true</bool>
</property>
<property name="interactive">
<bool>false</bool>
</property>
</widget>
</item>
<item row="0" column="4">
<widget class="QPushButton" name="playButton">
<property name="minimumSize">
<size>
<width>0</width>
<height>83</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>30</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip">
<string>play simulation</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Easing</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="easingShapeComboBox">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>70</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip">
<string>easing type</string>
</property>
<item>
<property name="text">
<string>Linear</string>
</property>
</item>
<item>
<property name="text">
<string>Quad</string>
</property>
</item>
<item>
<property name="text">
<string>Cubic</string>
</property>
</item>
<item>
<property name="text">
<string>Quart</string>
</property>
</item>
<item>
<property name="text">
<string>Quint</string>
</property>
</item>
<item>
<property name="text">
<string>Sine</string>
</property>
</item>
<item>
<property name="text">
<string>Expo</string>
</property>
</item>
<item>
<property name="text">
<string>Circ</string>
</property>
</item>
<item>
<property name="text">
<string>Elastic</string>
</property>
</item>
<item>
<property name="text">
<string>Back</string>
</property>
</item>
<item>
<property name="text">
<string>Bounce</string>
</property>
</item>
</widget>
</item>
<item row="1" column="2">
<widget class="QLabel" name="label_6">
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
</property>
<property name="text">
<string>Subtype</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="3" colspan="2">
<widget class="QComboBox" name="easingExtremesComboBox">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>easing subtype</string>
</property>
<item>
<property name="text">
<string>In</string>
</property>
</item>
<item>
<property name="text">
<string>Out</string>
</property>
</item>
<item>
<property name="text">
<string>InOut</string>
</property>
</item>
<item>
<property name="text">
<string>OutIn</string>
</property>
</item>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Duration</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QSpinBox" name="durationSpinBox">
<property name="maximumSize">
<size>
<width>70</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip">
<string>duration</string>
</property>
<property name="specialValueText">
<string>INVALID</string>
</property>
<property name="suffix">
<string> ms</string>
</property>
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>9999999</number>
</property>
<property name="singleStep">
<number>10</number>
</property>
<property name="value">
<number>250</number>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QLabel" name="label">
<property name="text">
<string>Amplitude</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="2" column="3" colspan="2">
<widget class="QDoubleSpinBox" name="amplitudeSpinBox">
<property name="maximumSize">
<size>
<width>70</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip">
<string>easing amplitude (only for Elastic and Bounce curves)</string>
</property>
<property name="specialValueText">
<string>INVALID</string>
</property>
<property name="decimals">
<number>3</number>
</property>
<property name="maximum">
<double>999999.989999999990687</double>
</property>
<property name="singleStep">
<double>0.050000000000000</double>
</property>
<property name="value">
<double>1.000000000000000</double>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Period</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QDoubleSpinBox" name="periodSpinBox">
<property name="maximumSize">
<size>
<width>70</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip">
<string>easing period (only for Elastic curve)</string>
</property>
<property name="specialValueText">
<string>INVALID</string>
</property>
<property name="decimals">
<number>3</number>
</property>
<property name="maximum">
<double>999999.989999999990687</double>
</property>
<property name="singleStep">
<double>0.010000000000000</double>
</property>
<property name="value">
<double>0.300000000000000</double>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Overshoot</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="3" column="3" colspan="2">
<widget class="QDoubleSpinBox" name="overshootSpinBox">
<property name="maximumSize">
<size>
<width>70</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip">
<string>easing overshoot (only for Back curve)</string>
</property>
<property name="specialValueText">
<string>INVALID</string>
</property>
<property name="decimals">
<number>3</number>
</property>
<property name="maximum">
<double>999999.989999999990687</double>
</property>
<property name="singleStep">
<double>0.050000000000000</double>
</property>
<property name="value">
<double>1.700000000000000</double>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -0,0 +1,288 @@
#include "easinggraph.h"
#include <QPainter>
#include <QStyleOptionGraphicsItem>
#include <math.h>
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;i<length;i++) {
qreal progress = i/qreal(length);
qreal value = m_curveFunction.valueForProgress(progress);
int x = int(length*progress);
int y = int(breadth*(1-value));
path.lineTo(x,y);
}
QRectF pathRect = path.controlPointRect();
if ( (pathRect.height()>breadth)) {
// 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;i<length;i++) {
qreal progress = i/qreal(length);
qreal value = m_curveFunction.valueForProgress(progress);
int x = int(length*progress);
int y = int(scale*(breadth*(1-value)+displacement));
path.lineTo(x,y);
}
drawZero = true;
}
painter->setBrush(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 (y<breadth)
painter->drawLine(0,y,length,y);
}
painter->setPen(m_color);
painter->drawPath(path);
painter->restore();
delete painter;
}
QT_END_NAMESPACE

View File

@@ -0,0 +1,91 @@
#ifndef EASINGGRAPH_H
#define EASINGGRAPH_H
//#include <QtDeclarative/qdeclarativeitem.h>
#include <QWidget>
#include <QEasingCurve>
#include <QHash>
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 <QString,QEasingCurve::Type> m_availableNames;
};
QT_END_NAMESPACE
//QML_DECLARE_TYPE(EasingGraph)
QT_END_HEADER
#endif // EASINGGRAPH_H

View File

@@ -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

View File

@@ -0,0 +1,7 @@
<RCC>
<qresource prefix="/">
<file>qt_logo.png</file>
<file>playicon.png</file>
<file>stopicon.png</file>
</qresource>
</RCC>

Binary file not shown.

After

Width:  |  Height:  |  Size: 230 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 194 B

View File

@@ -14,10 +14,10 @@
#include <qmldesignerplugin.h>
#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<EasingContextPane*>(m_currentWidget);
if (easingWidget)
easingWidget->setProperties(propertyReader);
ContextPaneWidgetImage *imageWidget = qobject_cast<ContextPaneWidgetImage*>(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

View File

@@ -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;

View File

@@ -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);

View File

@@ -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 \