From ed19fa0b1538f5c6ebbb545eab4d7cf50db0a4a9 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 18 Jun 2009 17:13:49 +1000 Subject: (Very) Basic FlowView prototype --- examples/declarative/flowview/flowview.qml | 108 ++++++++++ src/declarative/fx/fx.pri | 2 + src/declarative/fx/qfxflowview.cpp | 320 +++++++++++++++++++++++++++++ src/declarative/fx/qfxflowview.h | 103 ++++++++++ src/declarative/timeline/qmltimeline.h | 2 +- 5 files changed, 534 insertions(+), 1 deletion(-) create mode 100644 examples/declarative/flowview/flowview.qml create mode 100644 src/declarative/fx/qfxflowview.cpp create mode 100644 src/declarative/fx/qfxflowview.h diff --git a/examples/declarative/flowview/flowview.qml b/examples/declarative/flowview/flowview.qml new file mode 100644 index 0000000..5609500 --- /dev/null +++ b/examples/declarative/flowview/flowview.qml @@ -0,0 +1,108 @@ +Rect { + width: 800 + height: 800 + color: "black" + + Rect { + id: MyPhone + transformOrigin: "Center" + anchors.centeredIn: parent + width: 800 + height: 480 + + states: State { + name: "rotated" + SetProperties { target: ListView; z: 2 } + } + + color: "lightsteelblue" + + VisualModel { + id: Model + model: ListModel { + ListElement { stuff: "red" } + ListElement { stuff: "yellow" } + ListElement { stuff: "blue" } + ListElement { stuff: "green" } + ListElement { stuff: "orange" } + ListElement { stuff: "lightblue" } + } + delegate: Package { + Item { id: List; Package.name: "list"; width:120; height: 400; } + Item { id: Grid; Package.name: "grid"; width:400; height: 133; } + Rect { id: MyContent; width:400; height: 133; color: stuff; } + + StateGroup { + states: [ + State { + name: "InList" + when: MyPhone.state == "rotated" + ParentChange { target: MyContent; parent: List } + SetProperties { target: MyContent; x: 133; y: 0; rotation: 90} + }, + State { + name: "InGrid" + when: MyPhone.state != "rotated" + ParentChange { target: MyContent; parent: Grid } + SetProperties { target: MyContent; x: 0; y: 0; } + } + ] + transitions: Transition { + fromState: "*"; toState: "*"; + SequentialAnimation { + ParentChangeAction{} + NumericAnimation { properties: "x,y,rotation" } + } + } + } + + } + } + + Rect { + width: 800 + height: 30 + } + + Item { + FlowView { + id: ListView + vertical: true + y: 40 + x: 40 + width: 800 + height: 400 + column: 1 + model: Model.parts.list + } + + FlowView { + z: 1 + y: 40 + width: 800 + height: 400 + column: 2 + model: Model.parts.grid + } + } + + Rect { + width: 800 + height: 30 + anchors.bottom: parent.bottom + } + } + + Rect { + width: 80 + height: 80 + anchors.right: parent.right + anchors.bottom: parent.bottom + Text { text: "Switch" } + MouseRegion { + anchors.fill: parent + onClicked: if(MyPhone.state == "rotated") MyPhone.state=""; else MyPhone.state = "rotated"; + } + } + +} diff --git a/src/declarative/fx/fx.pri b/src/declarative/fx/fx.pri index 90820fa..1c819e7 100644 --- a/src/declarative/fx/fx.pri +++ b/src/declarative/fx/fx.pri @@ -15,6 +15,7 @@ HEADERS += \ fx/qfxfocuspanel.h \ fx/qfxfocusrealm.h \ fx/qfxgridview.h \ + fx/qfxflowview.h \ fx/qfxhighlightfilter.h \ fx/qfximage.h \ fx/qfxpainteditem.h \ @@ -63,6 +64,7 @@ SOURCES += \ fx/qfxfocuspanel.cpp \ fx/qfxfocusrealm.cpp \ fx/qfxgridview.cpp \ + fx/qfxflowview.cpp \ fx/qfxhighlightfilter.cpp \ fx/qfximage.cpp \ fx/qfxpainteditem.cpp \ diff --git a/src/declarative/fx/qfxflowview.cpp b/src/declarative/fx/qfxflowview.cpp new file mode 100644 index 0000000..911fc3d --- /dev/null +++ b/src/declarative/fx/qfxflowview.cpp @@ -0,0 +1,320 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 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 the GNU General Public License version 3.0 requirements will be +** met: 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. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qfxvisualitemmodel.h" +#include "qfxflowview.h" + +QT_BEGIN_NAMESPACE + +QFxFlowView::QFxFlowView() +: m_columns(0), m_model(0), m_vertical(false), m_dragItem(0), m_dragIdx(-1) +{ + setAcceptedMouseButtons(Qt::LeftButton); + setOptions(MouseEvents); +} + +QFxVisualItemModel *QFxFlowView::model() const +{ + return m_model; +} + +void QFxFlowView::setModel(QFxVisualItemModel *m) +{ + m_model = m; + refresh(); +} + +int QFxFlowView::columns() const +{ + return m_columns; +} + +void QFxFlowView::setColumns(int c) +{ + m_columns = c; + refresh(); +} + +bool QFxFlowView::vertical() const +{ + return m_vertical; +} + +void QFxFlowView::setVertical(bool v) +{ + m_vertical = v; +} + +class QFxFlowViewValue : public QmlTimeLineValue +{ +public: + enum Property { xProperty, yProperty }; + + QFxFlowViewValue(QFxItem *item, Property p) + : m_item(item), m_property(p) {} + + qreal value() const { + return (m_property == xProperty)?m_item->x():m_item->y(); + } + void setValue(qreal v) { + if (m_property == xProperty) m_item->setX(v); + else m_item->setY(v); + } +private: + QFxItem *m_item; + Property m_property; +}; + +void QFxFlowView::refresh() +{ + if (m_model && m_columns >= 1) { + for (int ii = 0; ii < m_model->count(); ++ii) { + QFxItem *item = m_model->item(ii); + item->setParent(this); + item->setZ(0); + m_items << item; + } + + reflow(); + } +} + +void QFxFlowView::reflow(bool animate) +{ + qreal y = 0; + qreal maxY = 0; + qreal x = 0; + if (animate) + clearTimeLine(); + for (int ii = 0; ii < m_items.count(); ++ii) { + if (0 == (ii % m_columns)) { + y += maxY; + maxY = 0; + x = 0; + } + + QFxItem *item = m_items.at(ii); + if (animate) { + if (vertical()) + moveItem(item, QPointF(y, x)); + else + moveItem(item, QPointF(x, y)); + } else { + if (vertical()) { + item->setX(y); + item->setY(x); + } else { + item->setX(x); + item->setY(y); + } + } + if (vertical()) { + x += item->height(); + maxY = qMax(maxY, item->width()); + } else { + x += item->width(); + maxY = qMax(maxY, item->height()); + } + } +} + +void QFxFlowView::reflowDrag(const QPointF &dp) +{ + qreal y = 0; + qreal maxY = 0; + qreal x = 0; + + int flowedItems = 0; + + clearTimeLine(); + + QList items; + + bool dragUsed = false; + bool dragSeen = false; + for (int ii = 0; ii < m_items.count(); ++ii) { + if (0 == (ii % m_columns)) { + y += maxY; + maxY = 0; + x = 0; + } + + QFxItem *item = m_items.at(ii); + if (item == m_dragItem) + dragSeen = true; + if (item == m_dragItem && dragUsed) + continue; + QRectF r; + if (vertical()) + r = QRectF(y, x, item->width(), item->height()); + else + r = QRectF(x, y, item->width(), item->height()); + if (r.contains(dp)) { + dragUsed = true; + if (dragSeen) + m_dragIdx = items.count() + 1; + else + m_dragIdx = items.count(); + + items.append(m_dragItem); + if (m_dragItem != item) { + if (dragSeen) + items.insert(items.count() - 1, item); + else + items.append(item); + } + } else { + if (m_dragItem != item) + items.append(item); + } + + if (vertical()) { + x += item->height(); + maxY = qMax(maxY, item->width()); + } else { + x += item->width(); + maxY = qMax(maxY, item->height()); + } + } + + y = 0; + maxY = 0; + x = 0; + clearTimeLine(); + for (int ii = 0; ii < items.count(); ++ii) { + if (0 == (ii % m_columns)) { + y += maxY; + maxY = 0; + x = 0; + } + + QFxItem *item = items.at(ii); + if (item != m_dragItem) { + if (vertical()) + moveItem(item, QPointF(y, x)); + else + moveItem(item, QPointF(x, y)); + } + if (vertical()) { + x += item->height(); + maxY = qMax(maxY, item->width()); + } else { + x += item->width(); + maxY = qMax(maxY, item->height()); + } + } + +} + +void QFxFlowView::moveItem(QFxItem *item, const QPointF &p) +{ + QFxFlowViewValue *xv = new QFxFlowViewValue(item, QFxFlowViewValue::xProperty); + QFxFlowViewValue *yv = new QFxFlowViewValue(item, QFxFlowViewValue::yProperty); + m_values << xv << yv; + m_timeline.move(*xv, p.x(), 100); + m_timeline.move(*yv, p.y(), 100); +} + +#include + +void QFxFlowView::mousePressEvent(QGraphicsSceneMouseEvent *event) +{ + for (int ii = 0; ii < m_items.count(); ++ii) { + QFxItem *item = m_items.at(ii); + QRectF r = rectForItem(ii); + + if (r.contains(event->pos())) { + m_dragItem = item; + m_dragItem->setZ(1); + m_dragOffset = r.topLeft() - event->pos(); + event->accept(); + return; + } + } + event->ignore(); +} + +QRectF QFxFlowView::rectForItem(int idx) const +{ + QFxItem *item = m_items.at(idx); + QRectF r(item->x(), item->y(), item->width(), item->height()); + return r; +} + +void QFxFlowView::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) +{ + if (m_dragItem) { + m_dragItem->setZ(0); + + clearTimeLine(); + + m_items.removeAll(m_dragItem); + m_items.insert(m_dragIdx, m_dragItem); + reflow(true); + m_dragItem = 0; + m_dragIdx = -1; + } +} + +void QFxFlowView::clearTimeLine() +{ + m_timeline.clear(); + qDeleteAll(m_values); + m_values.clear(); +} + +void QFxFlowView::mouseMoveEvent(QGraphicsSceneMouseEvent *event) +{ + if (m_dragItem) { + QPointF p = event->pos() + m_dragOffset; + m_dragItem->setX(p.x()); + m_dragItem->setY(p.y()); + + for (int ii = 0; ii < m_items.count(); ++ii) { + if (m_items.at(ii) != m_dragItem && rectForItem(ii).contains(event->pos())) { + reflowDrag(event->pos()); + } + } + } +} +QML_DEFINE_TYPE(QFxFlowView,FlowView); + +QT_END_NAMESPACE diff --git a/src/declarative/fx/qfxflowview.h b/src/declarative/fx/qfxflowview.h new file mode 100644 index 0000000..a18a4c7 --- /dev/null +++ b/src/declarative/fx/qfxflowview.h @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 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 the GNU General Public License version 3.0 requirements will be +** met: 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. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QFXFLOWVIEW_H +#define QFXFLOWVIEW_H + +#include +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) +class QFxVisualItemModel; +class QFxFlowViewValue; +class Q_DECLARATIVE_EXPORT QFxFlowView : public QFxItem +{ + Q_OBJECT + Q_PROPERTY(QFxVisualItemModel *model READ model WRITE setModel) + Q_PROPERTY(int column READ columns WRITE setColumns); + Q_PROPERTY(bool vertical READ vertical WRITE setVertical); + +public: + QFxFlowView(); + + QFxVisualItemModel *model() const; + void setModel(QFxVisualItemModel *); + + int columns() const; + void setColumns(int); + + bool vertical() const; + void setVertical(bool); + + virtual void mousePressEvent(QGraphicsSceneMouseEvent *event); + virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); + virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event); + +private: + QRectF rectForItem(int idx) const; + void refresh(); + void reflow(bool animate = false); + void reflowDrag(const QPointF &); + void clearTimeLine(); + int m_columns; + QFxVisualItemModel *m_model; + QList m_items; + bool m_vertical; + void moveItem(QFxItem *item, const QPointF &); + + QPointF m_dragOffset; + QFxItem *m_dragItem; + + QmlTimeLine m_timeline; + QList m_values; + int m_dragIdx; +}; +QML_DECLARE_TYPE(QFxFlowView); + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QFXFLOWVIEW_H diff --git a/src/declarative/timeline/qmltimeline.h b/src/declarative/timeline/qmltimeline.h index 23bdd64..627ec79 100644 --- a/src/declarative/timeline/qmltimeline.h +++ b/src/declarative/timeline/qmltimeline.h @@ -128,7 +128,7 @@ class Q_DECLARATIVE_EXPORT QmlTimeLineValue : public QmlTimeLineObject public: QmlTimeLineValue(qreal v = 0.) : _v(v) {} - qreal value() const { return _v; } + virtual qreal value() const { return _v; } virtual void setValue(qreal v) { _v = v; } QmlTimeLine *timeLine() const { return _t; } -- cgit v0.12