summaryrefslogtreecommitdiffstats
path: root/s-curve
diff options
context:
space:
mode:
authorAriya Hidayat <ariya.hidayat@trolltech.com>2009-03-02 10:28:23 +0100
committerAriya Hidayat <ariya.hidayat@trolltech.com>2009-03-02 10:28:23 +0100
commit2d03efa01a3da5a82e2b1cc107be5b87e789a19c (patch)
treede7a270aa039d34cbcbb2fca28076e281518477d /s-curve
parent08a2cb59d59a89a9e68bc870a960a76e834fcd8e (diff)
Add simple custom timeline demo
Diffstat (limited to 's-curve')
-rw-r--r--s-curve/form.ui187
-rw-r--r--s-curve/s-curve.cpp231
-rw-r--r--s-curve/s-curve.pro4
3 files changed, 422 insertions, 0 deletions
diff --git a/s-curve/form.ui b/s-curve/form.ui
new file mode 100644
index 0000000..c4ccdca
--- /dev/null
+++ b/s-curve/form.ui
@@ -0,0 +1,187 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Form</class>
+ <widget class="QWidget" name="Form">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>274</width>
+ <height>449</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Timeline Demo</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <widget class="QGroupBox" name="groupBox">
+ <property name="title">
+ <string>Timeline curve shape</string>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QRadioButton" name="easeInButton">
+ <property name="text">
+ <string>Ease in</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="easeOutButton">
+ <property name="text">
+ <string>Ease out</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="easeInOutButton">
+ <property name="text">
+ <string>Ease in out</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="linearButton">
+ <property name="text">
+ <string>Linear</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="sCurveButton">
+ <property name="text">
+ <string>S-curve</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_4">
+ <item>
+ <widget class="QLabel" name="curveLabel">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Curve adjustment</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QSlider" name="curveSlider">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="minimum">
+ <number>2</number>
+ </property>
+ <property name="maximum">
+ <number>6</number>
+ </property>
+ <property name="value">
+ <number>5</number>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QFrame" name="frame">
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QGraphicsView" name="graphicsView">
+ <property name="verticalScrollBarPolicy">
+ <enum>Qt::ScrollBarAlwaysOff</enum>
+ </property>
+ <property name="horizontalScrollBarPolicy">
+ <enum>Qt::ScrollBarAlwaysOff</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Speed:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QSlider" name="speedSlider">
+ <property name="value">
+ <number>50</number>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <item>
+ <widget class="QToolButton" name="showButton">
+ <property name="text">
+ <string>Show Panel</string>
+ </property>
+ <property name="toolButtonStyle">
+ <enum>Qt::ToolButtonTextBesideIcon</enum>
+ </property>
+ <property name="arrowType">
+ <enum>Qt::LeftArrow</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="hideButton">
+ <property name="text">
+ <string>Hide Panel</string>
+ </property>
+ <property name="toolButtonStyle">
+ <enum>Qt::ToolButtonTextBesideIcon</enum>
+ </property>
+ <property name="arrowType">
+ <enum>Qt::RightArrow</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/s-curve/s-curve.cpp b/s-curve/s-curve.cpp
new file mode 100644
index 0000000..3677ea6
--- /dev/null
+++ b/s-curve/s-curve.cpp
@@ -0,0 +1,231 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Graphics Dojo project on Qt Labs.
+**
+** This file may be used under the terms of the GNU General Public
+** License version 2.0 or 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of
+** this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+#include <QtGui>
+#include "ui_form.h"
+
+#define PANEL_WIDTH 150
+#define PANEL_MARGIN 20
+
+class CustomTimeLine: public QTimeLine
+{
+private:
+ qreal m_factor;
+ qreal m_offset;
+ qreal m_range;
+
+public:
+ bool useLogisticFunction;
+
+ CustomTimeLine(): QTimeLine(), useLogisticFunction(false) {
+ setFactor(4);
+ }
+
+ void setFactor(int factor) {
+ m_factor = factor;
+ qreal max = 1 / (1 + exp(-factor));
+ m_offset = 1 / (1 + exp(factor));
+ m_range = max - m_offset;
+ }
+
+ virtual qreal valueForTime(int msec) const {
+ if (useLogisticFunction) {
+ // this is normalized x
+ qreal x = static_cast<qreal>(msec) / duration();
+
+ // make it two-sided, 0 is the center
+ qreal xs = x * 2 * m_factor - m_factor;
+
+ // the simple logistic function
+ qreal y = 1 / (1 + exp(-xs));
+
+ // normalize to 0..1
+ y = (y - m_offset) / m_range;
+
+ return y;
+ }
+ else
+ return QTimeLine::valueForTime(msec);
+ }
+};
+
+class Panel: public QWidget
+{
+Q_OBJECT
+
+private:
+ QListWidget *m_list;
+
+public:
+ Panel(): QWidget() {
+ m_list = new QListWidget(this);
+ m_list->addItems(QColor::colorNames());
+
+ // fixed position, no layout nor container
+ m_list->move(0, 0);
+ }
+
+protected:
+ void resizeEvent(QResizeEvent*) {
+ if (m_list->height() != height())
+ m_list->resize(PANEL_WIDTH, height());
+ }
+};
+
+class TimeLineDemo: public QWidget
+{
+Q_OBJECT
+
+private:
+ QWidget *m_panel;
+ CustomTimeLine *m_timeLine;
+ QHash<QRadioButton*, int> m_curveMap;
+ QGraphicsScene *m_scene;
+ QGraphicsEllipseItem *m_curveDot;
+ QGraphicsPathItem *m_curvePath;
+ Ui::Form form;
+
+public:
+ TimeLineDemo(): QWidget() {
+
+ form.setupUi(this);
+ form.hideButton->hide();
+
+ m_panel = new Panel;
+ m_panel->setWindowFlags(Qt::FramelessWindowHint |
+ Qt::X11BypassWindowManagerHint |
+ Qt::Tool);
+ m_panel->hide();
+ m_panel->resize(0, 0);
+
+ m_timeLine = new CustomTimeLine;
+ m_timeLine->setFrameRange(0, PANEL_WIDTH);
+ connect(m_timeLine, SIGNAL(frameChanged(int)), SLOT(setSlidePosition(int)));
+ connect(m_timeLine, SIGNAL(stateChanged(QTimeLine::State)), SLOT(changeState()));
+ connect(m_timeLine, SIGNAL(finished()), m_timeLine, SLOT(toggleDirection()));
+
+ connect(form.hideButton, SIGNAL(clicked()), m_timeLine, SLOT(start()));
+ connect(form.showButton, SIGNAL(clicked()), m_timeLine, SLOT(start()));
+ connect(form.easeInButton, SIGNAL(toggled(bool)), SLOT(adjustCurveShape()));
+ connect(form.easeOutButton, SIGNAL(toggled(bool)), SLOT(adjustCurveShape()));
+ connect(form.easeInOutButton, SIGNAL(toggled(bool)), SLOT(adjustCurveShape()));
+ connect(form.linearButton, SIGNAL(toggled(bool)), SLOT(adjustCurveShape()));
+ connect(form.sCurveButton, SIGNAL(toggled(bool)), SLOT(adjustCurveShape()));
+ connect(form.curveSlider, SIGNAL(valueChanged(int)), SLOT(changeCurveFactor(int)));
+
+ m_curveMap[form.easeInButton] = static_cast<int>(QTimeLine::EaseInCurve);
+ m_curveMap[form.easeOutButton] = static_cast<int>(QTimeLine::EaseOutCurve);
+ m_curveMap[form.easeInOutButton] = static_cast<int>(QTimeLine::EaseInCurve);
+ m_curveMap[form.linearButton] = static_cast<int>(QTimeLine::LinearCurve);
+
+ m_scene = new QGraphicsScene(this);
+ form.graphicsView->setScene(m_scene);
+ form.graphicsView->setTransform(QTransform().scale(1, -1));
+ form.graphicsView->setRenderHints(QPainter::Antialiasing);
+ m_scene->addRect(0, 0, PANEL_WIDTH, PANEL_WIDTH, QPen(Qt::blue, 0.5));
+ m_curveDot = m_scene->addEllipse(0, 0, 10, 10, QPen(), QBrush(Qt::red));
+ m_curvePath = m_scene->addPath(QPainterPath(), QPen(Qt::black, 1.5));
+ m_timeLine->setFactor(form.curveSlider->value());
+ adjustCurvePath();
+ }
+
+ ~TimeLineDemo() {
+ delete m_panel;
+ }
+
+private:
+
+ void adjustCurvePath() {
+ QPainterPath path;
+ path.moveTo(0, 0);
+ for (qreal i = 0.0; i <= 32.0; ++i) {
+ qreal x = i / 32.0;
+ int t = static_cast<int>(x * m_timeLine->duration());
+ qreal y = m_timeLine->valueForTime(t);
+ path.lineTo(PANEL_WIDTH * x, PANEL_WIDTH * y);
+ }
+ m_curvePath->setPath(path);
+ }
+
+public slots:
+
+ void changeState() {
+ int speed = form.speedSlider->value();
+ m_timeLine->setDuration(1200 - speed*10);
+ bool notrunning = m_timeLine->state() == QTimeLine::NotRunning;
+ form.showButton->setEnabled(notrunning);
+ form.hideButton->setEnabled(notrunning);
+ form.showButton->setVisible(m_timeLine->direction() == QTimeLine::Backward);
+ form.hideButton->setVisible(!form.showButton->isVisible());
+ m_panel->show();
+ m_panel->raise();
+ }
+
+private slots:
+
+ void setSlidePosition(int pos) {
+ m_panel->resize(pos, m_panel->height());
+ m_panel->move(this->pos() - QPoint(pos, -PANEL_MARGIN - 20));
+ qreal t = static_cast<qreal>(m_timeLine->currentTime());
+ qreal x = t * PANEL_WIDTH / m_timeLine->duration();
+ m_curveDot->setPos(x - 5, pos - 5);
+ }
+
+ void adjustCurveShape() {
+ QRadioButton *button = qobject_cast<QRadioButton*>(sender());
+ int c = m_curveMap[button];
+ QTimeLine::CurveShape shape = static_cast<QTimeLine::CurveShape>(c);
+ m_timeLine->useLogisticFunction = (button == form.sCurveButton);
+ if (button)
+ m_timeLine->setCurveShape(shape);
+ adjustCurvePath();
+ form.curveSlider->setEnabled(button == form.sCurveButton);
+ form.curveLabel->setEnabled(button == form.sCurveButton);
+ }
+
+ void changeCurveFactor(int factor) {
+ m_timeLine->setFactor(factor);
+ adjustCurvePath();
+ }
+
+protected:
+ void moveEvent(QMoveEvent *event) {
+ m_panel->move(m_panel->pos() + event->pos() - event->oldPos());
+ }
+
+ void resizeEvent(QResizeEvent*) {
+ m_panel->resize(m_panel->width(), height() - 2 * PANEL_MARGIN);
+ }
+};
+
+#include "s-curve.moc"
+
+int main(int argc, char *argv[])
+{
+ QApplication app(argc, argv);
+
+ TimeLineDemo demo;
+ demo.show();
+
+ return app.exec();
+}
diff --git a/s-curve/s-curve.pro b/s-curve/s-curve.pro
new file mode 100644
index 0000000..56a433f
--- /dev/null
+++ b/s-curve/s-curve.pro
@@ -0,0 +1,4 @@
+TEMPLATE = app
+TARGET = s-curve
+SOURCES = s-curve.cpp
+FORMS = form.ui