diff --git a/HIG/source/layout/gestures.rst b/HIG/source/layout/gestures.rst
index a84a23c..ffabb92 100644
--- a/HIG/source/layout/gestures.rst
+++ b/HIG/source/layout/gestures.rst
@@ -1,68 +1,130 @@
Gestures
========
Purpose
-------
Gestures are a way to perform common tasks faster und more intuitively. They
should never be the only way to perform an action but rather be treated like a
keybord shortcut.
Principles
----------
Unless you create a game, you should avoid to use non standard gestures.
Don't abuse the standard gestures to trigger none standard actions. For example
don't use a pinch to delete an item, but only for scaling content.
Avoid to interfer with system wide screen egde gestures like pulling down the
top panel on plasma mobile.
-Guidelines
-----------
+Gestures
+--------
+
+These type of gestures are used commonly, both on desktop and on mobile. They
+can be used to navigate, trigger actions, or manipulate content
+
+
+Tab
+~~~
+
+.. raw:: html
+
+
+
+A tab is handled like a mouse click. It can be used to navigate, trigger
+actions, or manipulate content.
+
+Long press
+~~~~~~~~~~
+
+Can trigger aditional actions on an item or a control.
+
+Swipe
+~~~~~
+
+.. raw:: html
+
+
+
+Navigate between views, activate actions on items.
+
+Pinch
+~~~~~
-Common gestures
-~~~~~~~~~~~~~~~
+.. raw:: html
+
+
+
+Scales content
-These gestures are used commonly, both on desktop and on mobile.
+Rotate
+~~~~~~
+
+.. raw:: html
+
+
+
+Rotate content
-=============================== =======================
-Gesture Action
-=============================== =======================
-Pinch Scales content
-Rotate Rotate content
-Tab Handled like a click
-Swipe Navigate between views, activate actions on
- items
Desktop
-^^^^^^^
+~~~~~~~
+
+Aditionally to the common gestures, there a several gestures on Plasma Desktop
+to invoke functionallity from the desktop enviroment.
+
+XXXX
+^^^^
+Switch workspace
-System
-=============================== =======================
-Gesture Action
-=============================== =======================
-XXXXX Switch workspace
-XXXX Show app overview
-...
+XXXX
+^^^^
+Show app overview
Mobile
-^^^^^^
+~~~~~~
+
+Aditionally to the common gestures, there a several common gestures on Plamsa
+Mobile.
+
+
+Edge swipe top
+^^^^^^^^^^^^^^
+
+Pull down top panel
+
+
+Edge swipe bottom
+^^^^^^^^^^^^^^^^^
+
+Pull up main menu
+
-System
+In plasma mobile there a also aditional common gestures to be used in
+applications.
-=============================== =======================
-Gesture Action
-=============================== =======================
-Edge swipe top Pull down top panel
-Edge swipe bottom Pull up main menu
+Edge swipe left
+^^^^^^^^^^^^^^^
+.. raw:: html
+
+
+
+Open the global drawer.
-Applications
-=============================== =======================
-Gesture Action
-=============================== =======================
-Edge swipe left Open the global drawer
-Edge swipe right Open the context drawer
+Edge swipe right
+^^^^^^^^^^^^^^^^
+Open the context drawer
diff --git a/HIG/source/layout/index.rst b/HIG/source/layout/index.rst
index 1c7a84b..b4aed63 100644
--- a/HIG/source/layout/index.rst
+++ b/HIG/source/layout/index.rst
@@ -1,19 +1,21 @@
Layout
======
.. toctree::
:maxdepth: 1
:caption: Contents:
:titlesonly:
:hidden:
units
metrics
alignment
onehand
+ gestures
* :doc:`units`
* :doc:`metrics`
* :doc:`alignment`
* :doc:`onehand`
+* :doc:`gestures`
diff --git a/HIG/source/qml/files/Folder.qml b/HIG/source/qml/files/Folder.qml
index 1bd07be..214ed73 100644
--- a/HIG/source/qml/files/Folder.qml
+++ b/HIG/source/qml/files/Folder.qml
@@ -1,86 +1,69 @@
/*
* Copyright 2018 Fabian Riethmayer
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import QtQuick 2.6
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.2
import org.kde.kirigami 2.4 as Kirigami
Kirigami.ScrollablePage {
property alias currentIndex: list.currentIndex;
property var pagemodel;
property var pageroot;
Kirigami.Theme.colorSet: Kirigami.Theme.View
title: pagemodel.name
id: page
background: Rectangle {
color: Kirigami.Theme.backgroundColor
}
/*header: Rectangle {
clip: true
id: header
color: "#3daee9"
height: searchField.implicitHeight + 2 * Kirigami.Units.largeSpacing
width: root.width
//border.width: 1
//border.color: "#bdc3c7"
TextField {
id: searchField
placeholderText: "Search"
anchors.centerIn: parent
anchors.margins: Kirigami.Units.largeSpacing
width: parent.width - 2 * Kirigami.Units.largeSpacing
}
}*/
ListView {
currentIndex: -1
id: list
model: pagemodel.subfolder
delegate: Kirigami.BasicListItem {
onClicked: {
pageroot.pageStack.push(Qt.resolvedUrl("Folder.qml"), {"pagemodel": pagemodel.subfolder.get(index), "pageroot": pageroot});
}
-
- contentItem: Row {
- spacing: 2 * Kirigami.Units.largeSpacing
-
- Item {
- width: Kirigami.Units.iconSizes.medium
- height: width
-
- Kirigami.Icon {
- width: Kirigami.Units.iconSizes.medium
- height: width
- source: model.icon
- }
- }
- Label {
- anchors.verticalCenter: parent.verticalCenter
- text: model.name
- }
- }
+ icon: model.icon
+ label: model.name
}
}
}
diff --git a/HIG/source/qml/layout/gestures/Pinch.qml b/HIG/source/qml/layout/gestures/Pinch.qml
index b64da30..273e1dc 100644
--- a/HIG/source/qml/layout/gestures/Pinch.qml
+++ b/HIG/source/qml/layout/gestures/Pinch.qml
@@ -1,126 +1,79 @@
/*
* Copyright 2018 Fabian Riethmayer
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import QtQuick 2.13
import QtQuick.Layouts 1.2
import QtQuick.Controls 2.2
import org.kde.kirigami 2.4 as Kirigami
import "../../lib/annotate.js" as A
import "../../addr/" as Addr
Rectangle {
width: 320
height: 600
id: root
Image {
anchors.fill: root
id: myImage
- source: "../../../img/wallpaper/next.png"
+ source: "../../../img/wallpaper/Cluster.png"
+ fillMode: Image.PreserveAspectCrop
+ smooth: true
+
+ Behavior on rotation {
+ id: behave
+ enabled: false
+ NumberAnimation {duration: 300; easing.type: Easing.Linear}
+ }
+ Behavior on scale {
+ enabled: behave.enabled
+ NumberAnimation {duration: 300; easing.type: Easing.Linear}
+ }
PinchArea {
id: pinchArea
anchors.fill: parent
pinch.target: myImage
- pinch.minimumRotation: -360
- pinch.maximumRotation: 360
+ pinch.minimumRotation: 0
+ pinch.maximumRotation: 0
pinch.minimumScale: 0.1
- pinch.maximumScale: 10
- pinch.dragAxis: Pinch.NoDrag
-
- // MouseArea {
- // id: dragArea
- // hoverEnabled: true
- // anchors.fill: parent
- // drag.target: img
- // scrollGestureEnabled: false // 2-finger-flick gesture should pass through to the Flickable
- //
- // onWheel: {
- // var scaleBefore = img.scale;
- // img.scale += img.scale * wheel.angleDelta.y / 120 / 10;
- // }
- // }
+ pinch.maximumScale: 3
+ pinch.dragAxis: Pinch.XAndYAxis
onPinchFinished: function(event) {
- console.log("pinching finished")
- console.log(JSON.stringify(event));
- //console.log(event.previousScale);
- }
-
- onPinchStarted: function(event) {
- console.log("pinching started")
- console.log(JSON.stringify(event));
- }
-
- onPinchUpdated: function(event) {
- console.log("pinch updated")
- console.log(JSON.stringify(event));
+ behave.enabled = true
+ myImage.rotation = 0
+ myImage.scale = 1
}
}
- }
-
-// MultiPointTouchArea {
-// id: pinchArea
-// anchors.fill: parent
-// // touchPoints: [
-// // TouchPoint { id: point1 },
-// // TouchPoint { id: point2 }
-// // ]
-//
-// onGestureStarted: function(gesture) {
-// console.log("gesture");
-// console.log(gesture);
-// }
-// onPressed: function(gesture) {
-// console.log("pressed");
-// }
-// onReleased: function(gesture) {
-// console.log("released");
-// }
-// onUpdated: function(gesture) {
-// console.log("updated");
-// }
-// }
-
+ }
// HACK coordinates are only final after a small delay
Timer {
interval: 1000
repeat: false
running: true
onTriggered: {
var a = new A.An(pinchArea);
- //a.tree();
- a.pinch({x: +130, x: 0});
+ a.pinch({ from: Qt.rect(0, 0, 20, 20), distance: 100});
}
}
-/*
- Timer {
- id: hideTimer
- interval: 2000
- repeat: false
- running: false
- onTriggered: {
- var a = new A.An(root);
- a.find("swipelistitem").first().touch({x: 0, y: 0});
- }
- }*/
}
diff --git a/HIG/source/qml/layout/gestures/Swipe.qml b/HIG/source/qml/layout/gestures/Swipe.qml
index 2b3b9f7..866f4e7 100644
--- a/HIG/source/qml/layout/gestures/Swipe.qml
+++ b/HIG/source/qml/layout/gestures/Swipe.qml
@@ -1,58 +1,58 @@
/*
* Copyright 2018 Fabian Riethmayer
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import QtQuick 2.2
import QtQuick.Layouts 1.2
import QtQuick.Controls 2.2
import org.kde.kirigami 2.4 as Kirigami
import "../../lib/annotate.js" as A
import "../../addr/" as Addr
Rectangle {
width: 320
height: 600
Addr.Addressbook {
id: root
}
// HACK coordinates are only final after a small delay
Timer {
interval: 1000
repeat: false
running: true
onTriggered: {
var a = new A.An(root);
//a.tree();
- a.find("swipelistitem").first().swipe({fromX: +130, fromY: 0, toX: -80, toY: 0});
+ a.find("swipelistitem").first().swipe({fromX: +130, fromY: 0, toX: -120, toY: 0});
hideTimer.start();
}
}
Timer {
id: hideTimer
interval: 2000
repeat: false
running: false
onTriggered: {
var a = new A.An(root);
- a.find("swipelistitem").first().touch({x: 0, y: 0});
+ a.find("swipelistitem").first().touch({x: -50, y: 0});
}
}
}
diff --git a/HIG/source/qml/lib/Pinch.qml b/HIG/source/qml/lib/Pinch.qml
index fb601cd..25f780c 100644
--- a/HIG/source/qml/lib/Pinch.qml
+++ b/HIG/source/qml/lib/Pinch.qml
@@ -1,103 +1,126 @@
/*
* Copyright 2018 Fabian Riethmayer
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import QtQuick 2.2
import org.kde.kirigami 2.4 as Kirigami
import QtTest 1.2
+import "tools.js" as T
+
// Show a touch event
Item {
id: canvas
anchors.fill: parent;
- property int fromX
- property int fromY
+ // Define the pinch movement
+ property rect from
+ property rect to
+ property int duration : 300;
+
+ // For internal
+ property int i: 0
+ property real aStepX;
+ property real aStepY;
+ property real bStepX;
+ property real bStepY;
+ property var sequence;
- Touch {
- id: touch1
- fromX: canvas.fromX + 10
- fromY: canvas.fromY + 10
- toX: canvas.fromX + 100
- toY: canvas.fromY + 100
+ VisualTouchPoint {
+ id: touchPointA;
+ x: from.right
+ y: from.top
+ dur: duration
}
- Touch {
- id: touch2
- touchId: 1
- sequence: touch1.sequence
- fromX: canvas.fromX - 10
- fromY: canvas.fromY - 10
- toX: canvas.fromX - 100
- toY: canvas.fromY - 100
+ VisualTouchPoint {
+ id: touchPointB
+ x: from.left
+ y: from.bottom
+ dur: duration
}
TestEvent {
id: event
}
+ Timer {
+ id: swipeTimer
+ interval: 30
+ repeat: true
+ running: false
+ onTriggered: {
+ // Move both touch pointer
+ i++;
+ sequence.move(1, canvas.parent, from.right + i * aStepX, from.top + i * aStepY);
+ sequence.move(2, canvas.parent, from.left + i * bStepX, from.bottom + i * bStepY);
+ sequence.commit();
+
+ if (i == 10) {
+ running = false;
+ touchPointA.moved();
+ }
+ }
+ }
+
function pinch() {
- console.log("starting pinch");
+ touchPointA.animate = true;
+ touchPointB.animate = true;
+
+ // Calculate step size
+ // aStepX and aStepX should both > 0
+ // and bStepX and bStepY both < 0
+ // (or the other way around)
+ aStepX = (from.right - to.right) / 10
+ aStepY = -1 * (from.top - to.top) / 10
+ bStepX = (from.left - to.left) / 10
+ bStepY = -1 * (from.bottom - to.bottom) / 10
- var sequence = event.touchEvent(canvas.parent);
- sequence.press(0, canvas.parent, fromX - 20, fromY -20);
- sequence.press(1, canvas.parent, fromX + 20, fromY + 20);
- //sequence.press(2, canvas.parent, fromX + 20, fromY + 20);
- sequence.commit();
- console.log("pressed");
- sequence.move(0, canvas.parent, fromX - 50, fromY - 50);
- sequence.move(1, canvas.parent, fromX + 50, fromY + 50);
- console.log("move 1");
- sequence.commit();
-// var stepX = 10;
-// var stepY = 10;
-// var i = 1;
-// for (var i = 0; i < 10; i++) {
-// sequence.move(0, canvas.parent, fromX + -1 * i * stepX, fromY);
-// sequence.move(1, canvas.parent, fromX + i * stepX, fromY);
-// }
- delay(500, function() {
- sequence.move(0, canvas.parent, fromX -100, fromY - 90);
- sequence.move(1, canvas.parent, fromX + 200, fromY + 80);
- //sequence.move(2, canvas.parent, fromX + 200, fromY + 80);
+ // Wait till both touch points are pressed
+ T.join([touchPointA.pressed, touchPointB.pressed], function() {
+ sequence = event.touchEvent(canvas.parent);
+ sequence.press(1, canvas.parent, from.right, from.top);
+ sequence.press(2, canvas.parent, from.left, from.bottom);
sequence.commit();
- console.log("move 2");
+
+ // Move the visual touchpointer to the end
+ touchPointA.x = to.right;
+ touchPointA.y = to.top;
+ touchPointB.x = to.left;
+ touchPointB.y = to.bottom;
+
+ // Start the gesture
+ i = 0;
+ swipeTimer.start();
+ });
- delay(500, function() {
- sequence.release(0, canvas.parent, fromX - 100, fromY - 90);
- sequence.release(1, canvas.parent, fromX + 200, fromY + 80);
- sequence.commit();
- console.log("released");
- });
+ // Release after swipes are done
+ touchPointA.moved.connect(function() {
+ touchPointA.state = "RELEASED";
+ touchPointB.state = "RELEASED";
});
-// touch1.swipe();
-// touch2.swipe();
- }
-
- function myTimer() {
- return Qt.createQmlObject("import QtQuick 2.2; Timer {}", root);
- }
-
- function delay(delayTime, cb) {
- var timer = new myTimer();
- timer.interval = delayTime;
- timer.repeat = false;
- timer.triggered.connect(cb);
- timer.start();
+ touchPointA.released.connect(function() {
+ sequence.release(1, canvas.parent, to.right, to.top);
+ sequence.release(2, canvas.parent, to.left, to.bottom);
+ sequence.commit();
+ });
+
+ touchPointA.state = "PRESSED"
+ touchPointB.state = "PRESSED"
}
}
diff --git a/HIG/source/qml/lib/Touch.qml b/HIG/source/qml/lib/Touch.qml
index 83cd47c..8d493c5 100644
--- a/HIG/source/qml/lib/Touch.qml
+++ b/HIG/source/qml/lib/Touch.qml
@@ -1,179 +1,117 @@
/*
* Copyright 2018 Fabian Riethmayer
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import QtQuick 2.2
import org.kde.kirigami 2.4 as Kirigami
import QtTest 1.2
// Show a touch event
Item {
id: canvas
anchors.fill: parent;
property int fromX
property int fromY
property int toX
property int toY
property int dur: 300
property var sequence;
property int i: 0
property int touchId: 0
- Rectangle {
+ VisualTouchPoint {
+ x: fromX;
+ y: fromY;
id: touchPoint
-
- signal released()
- signal pressed()
- signal moved()
-
- state: "RELEASED"
-
- z: 1
- height: Kirigami.Units.iconSizes.small
- width: height
- color: "#331D99F3"
- radius: height / 2
- border.width: 1
- border.color: "#1D99F3"
-
- Behavior on x {
- id: animate
- enabled: false
- NumberAnimation {duration: dur}
- }
- Behavior on y {
- enabled: animate.enabled
- NumberAnimation {duration: dur}
- }
-
- states: [
- State {
- name: "PRESSED"
- PropertyChanges { target: touchPoint; color: "#FF1D99F3"; visible: true }
- }
- ]
-
- transitions: [
- Transition {
- from: "PRESSED"
- to: "RELEASED"
- SequentialAnimation {
- ColorAnimation {target: touchPoint; duration: 300}
- PropertyAction {target: touchPoint; property: "visible"; value: false}
- ScriptAction {
- script: touchPoint.released()
- }
- }
- },
- Transition {
- from: "RELEASED"
- to: "PRESSED"
- SequentialAnimation {
- PropertyAction {target: touchPoint; property: "visible"; value: true}
- ColorAnimation {target: touchPoint; duration: 300}
- ScriptAction {
- script: touchPoint.pressed()
- }
- }
- }
- ]
}
TestEvent {
id: event
}
// HACK to slow down the gesture
// needs to be synced with the animations of the touchPoint
Timer {
id: swipeTimer
- interval: 10
+ interval: 30
repeat: true
running: false
onTriggered: {
// Move the touch pointer
i++;
var stepX = (toX - fromX) / 10
var stepY = (toY - fromY) / 10
sequence.move(touchId, canvas.parent, fromX + i * stepX, toY + i * stepY);
- //console.log("move: " + (fromX + i * stepX) + "x" + (toY + i * stepY))
- //sequence.commit();
+ sequence.commit();
if (i == 10) {
running = false;
touchPoint.moved();
}
}
}
// Animate swipe
function swipe() {
- touchPoint.x = fromX;
- touchPoint.y = fromY;
- animate.enabled = true;
+
+ touchPoint.animate = true;
// Start swipe after animation is done
touchPoint.pressed.connect(function() {
touchPoint.x = toX;
touchPoint.y = toY;
if (!sequence) {
// Only create a new sequence if not 1 exists already
sequence = event.touchEvent(canvas.parent);
}
-// console.log(sequence);
-// console.log(touchId);
sequence.press(touchId, canvas.parent, fromX, fromY);
- console.log("press(" + touchId +"): " + fromX + "x" + fromY)
- //sequence.commit();
+ sequence.commit();
i = 0;
swipeTimer.start();
});
// Finish touch event
// Release touch pointer
touchPoint.moved.connect(function() {
sequence.release(touchId, canvas.parent, toX, toY);
- console.log("release(" + touchId +"): " + toX + "x" + toY)
- //console.log(sequence);
- //console.log(touchId);
- if (touchId == 1) {
- console.log("commit");
- sequence.commit();
- }
+ sequence.commit();
touchPoint.state = "RELEASED";
});
touchPoint.state = "PRESSED"
}
function touch() {
touchPoint.x = toX;
touchPoint.y = toY;
// Emit touch event after animation is done
touchPoint.pressed.connect(function() {
if (!sequence) {
sequence = event.touchEvent(canvas);
}
sequence.press(touchId, canvas, toX, toY);
sequence.commit();
+ touchPoint.state = "RELEASED"
+ });
+
+ touchPoint.released.connect(function() {
sequence.release(touchId, canvas, toX, toY);
sequence.commit();
- touchPoint.state = "RELEASED"
});
touchPoint.state = "PRESSED"
}
}
diff --git a/HIG/source/qml/lib/annotate.js b/HIG/source/qml/lib/annotate.js
index d67e4a2..c451657 100644
--- a/HIG/source/qml/lib/annotate.js
+++ b/HIG/source/qml/lib/annotate.js
@@ -1,366 +1,412 @@
var ruler = Qt.createComponent("Ruler.qml");
var brace = Qt.createComponent("Brace.qml");
var outline = Qt.createComponent("Outline.qml");
var messure = Qt.createComponent("Messure.qml");
var padding = Qt.createComponent("Padding.qml");
var mouse = Qt.createComponent("Mouse.qml");
var touch = Qt.createComponent("Touch.qml");
var pinch = Qt.createComponent("Pinch.qml");
+var rotate = Qt.createComponent("Rotate.qml");
// get classname and strip _QML of the name
function getClassName(obj) {
var str = obj.toString();
str = str.substring(0, str.indexOf("("));
if (str.search(/_QML/) !== -1) {
str = str.substring(0, str.indexOf("_QML"));
}
return str.toLowerCase();
}
// Merge 2 objects of options
function getOpts(opts, choices) {
for (var choice in choices) {
opts[choice] = choices[choice];
}
return opts;
}
// An extended array of QML elements
function An(node) {
this.nodes = [];
if (typeof node === "undefined") {
this.nodes = []
}
else if (typeof node === "Array") {
this.nodes = node;
}
else {
this.nodes = [node];
}
}
// Find an An of QML elements from this point down the subtrees
An.prototype.find = function(selector) {
var result = new An();
if (typeof selector === "string") {
selector = new Select(selector);
}
/* for debugging
for (var member in this) {
if (typeof this[member] !== "function") {
console.log(member + ": " + this[member]);
}
}*/
// iterate threw the children
// apply the selector and traverse down the tree
for (var n = 0; n < this.nodes.length; n++) {
var node = this.nodes[n];
for (var i = 0; i < node.children.length; i++) {
if (selector.match(node.children[i])) {
// Add matching element to result
result.nodes.push(node.children[i]);
}
if (node.children[i].children.length) {
// Merge matching results of subrtree
var child = new An(node.children[i]);
result.concat(child.find(selector));
}
}
}
return result;
}
An.prototype.inspect = function() {
for (var member in this.nodes[0]) {
if (typeof this[member] !== "function") {
console.log(member + ": " + this[member]);
}
}
return this;
}
// Search only direct children
An.prototype.children = function(selector) {
var result = new An();
if (typeof selector === "string") {
selector = new Select(selector);
}
for (var n = 0; n < this.nodes.length; n++) {
var node = this.nodes[n];
for (var i = 0; i < node.children.length; i++) {
if (selector.match(node.children[i])) {
// Add matching element to result
result.nodes.push(node.children[i]);
}
}
}
return result;
}
An.prototype.concat = function(n) {
this.nodes = this.nodes.concat(n.nodes);
}
An.prototype.first = function() {
if (this.nodes.length > 0) {
return new An(this.nodes[0]);
}
return new An();
}
An.prototype.last = function() {
if (this.nodes.length > 0) {
return new An(this.nodes[this.nodes.length - 1]);
}
return new An();
}
An.prototype.eq = function(n) {
if (this.nodes.length > n) {
return new An(this.nodes[n]);
}
return new An();
}
/**
* Simulate a mouse click on the nodes
*/
An.prototype.click = function(opt) {
var options = getOpts({
x: 0,
y: 0
}, opt);
for (var n = 0; n < this.nodes.length; n++) {
var node = this.nodes[n];
var x = node.mapToItem(null, 0, 0).x + Math.floor(node.width / 2) + options.x;
var y = node.mapToItem(null, 0, 0).y + Math.floor(node.height / 2) + options.y;
var m = mouse.createObject(root, {px: x, py: y});
m.click();
}
return this;
}
/**
* Simulate a swipe the nodes
*/
An.prototype.touch = function(opt) {
var options = getOpts({
x: 0,
y: 0
}, opt);
for (var n = 0; n < this.nodes.length; n++) {
var node = this.nodes[n];
var x = node.mapToItem(null, 0, 0).x + Math.floor(node.width / 2) + options.x;
var y = node.mapToItem(null, 0, 0).y + Math.floor(node.height / 2) + options.y;
var m = touch.createObject(root, {toX: x, toY: y});
m.touch();
}
return this;
}
/**
* Simulate a pinch the nodes
*/
An.prototype.pinch = function(opt) {
- var options = getOpts({
- x: 0,
- y: 0
- }, opt);
-
for (var n = 0; n < this.nodes.length; n++) {
var node = this.nodes[n];
- var x = node.mapToItem(null, 0, 0).x + Math.floor(node.width / 2) + options.x;
- var y = node.mapToItem(null, 0, 0).y + Math.floor(node.height / 2) + options.y;
- var m = pinch.createObject(root, {fromX: x, fromY: y});
+ // Translate rectangle to center of node
+ var oX = node.mapToItem(null, 0, 0).x + Math.floor(node.width / 2);
+ var oY = node.mapToItem(null, 0, 0).x + Math.floor(node.height / 2);
+ var width = opt.from.right - opt.from.left;
+ var height = opt.from.bottom - opt.from.top;
+
+ var from = Qt.rect(
+ opt.from.left + oX,
+ opt.from.top + oY,
+ width,
+ height
+ );
+ // Calculate to from the distance
+ var dig = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2));
+ var x = (opt.distance + dig) / dig;
+ var to = Qt.rect(
+ from.left - (width * x) / 2,
+ from.top - (height * x) / 2,
+ width * x,
+ height * x
+ );
+ // TODO add option for explicit to
+// var to = Qt.rect(
+// opt.to.left + oX,
+// opt.to.top + oY,
+// opt.to.right - opt.to.left,
+// opt.to.bottom - opt.to.top
+// );
+ var m = pinch.createObject(root, {from: from, to: to});
m.pinch();
}
return this;
}
+/**
+ * Simulate a pinch/rotate the nodes
+ */
+An.prototype.rotate = function(opt) {
+ for (var n = 0; n < this.nodes.length; n++) {
+ var node = this.nodes[n];
+ // Translate rectangle to center of node
+ var oX = node.mapToItem(null, 0, 0).x + Math.floor(node.width / 2);
+ var oY = node.mapToItem(null, 0, 0).x + Math.floor(node.height / 2);
+ var width = opt.from.right - opt.from.left;
+ var height = opt.from.bottom - opt.from.top;
+
+ var from = Qt.rect(
+ oX - 40,
+ oY - 40,
+ 80,
+ 80
+ );
+ var m = rotate.createObject(root, {from: from, angle: opt.angle});
+ m.rotate();
+ }
+ return this;
+}
+
/**
* Simulate a mouse hover on the nodes
*/
An.prototype.hover = function(opt) {
var options = getOpts({
x: 0,
y: 0,
animate: true
}, opt);
for (var n = 0; n < this.nodes.length; n++) {
var node = this.nodes[n];
var x = node.mapToItem(null, 0, 0).x + Math.floor(node.width / 2) + options.x;
var y = node.mapToItem(null, 0, 0).y + Math.floor(node.height / 2) + options.y;
var m = mouse.createObject(root, {px: x, py: y, animate: options.animate});
m.hover();
}
return this;
}
/**
* Simulate a touch
*/
An.prototype.swipe = function(opt) {
var options = getOpts({
fromX: 0,
fromY: 0,
toX: 0,
toY: 0
}, opt);
for (var n = 0; n < this.nodes.length; n++) {
var node = this.nodes[n];
var x = node.mapToItem(null, 0, 0).x + Math.floor(node.width / 2) + options.fromX;
var y = node.mapToItem(null, 0, 0).y + Math.floor(node.height / 2) - Kirigami.Units.iconSizes.smallMedium / 2 + options.fromY;
var t = touch.createObject(root, {fromX: x, fromY: y, toX: x + options.toX, toY: y + options.toY});
t.swipe();
}
return this;
}
/**
* Draw a tree of all the elements
*/
An.prototype.tree = function(lvl) {
if (typeof lvl === "undefined") {
lvl = ""
}
/* for debug
for (var member in this.nodes) {
if (typeof this[member] !== "function") {
console.log("|" + lvl + " " + member + ": " + (typeof this[member]));
}
}*/
for (var n = 0; n < this.nodes.length; n++) {
var node = this.nodes[n];
console.log("|" + lvl + " " + getClassName(node) + " " + node.toString() + " " + node.children.length);
for (var i = 0; i < node.children.length; i++) {
var child = new An(node.children[i]);
child.tree(lvl + "--");
}
}
}
/**
* Drawing annotation on the nodes
*/
An.prototype.draw = function(obj) {
//console.log(this.nodes)
for (var n = 0; n < this.nodes.length; n++) {
var node = this.nodes[n];
var opt;
for (var type in obj) {
if (Array.isArray(obj[type])) {
for (var i = 0; i < obj[type].length; i++) {
this._draw(node, type, obj[type][i]);
}
}
else {
this._draw(node, type, obj[type]);
}
}
}
return this;
}
/**
* Internal method to draw
*/
An.prototype._draw = function(node, type, opt) {
//console.log("drawing " + type)
switch (type) {
case "outline":
// Create outline object
outline.createObject(root, {item: node, label: opt.label, aspectratio: opt.aspectratio});
break
case "ruler":
// Draw ruler to show alignment
if (opt.offset) {
// No need for left or top since these are the defaults
switch (opt.offset) {
case "center":
opt.offset = opt.horizontal ? node.mapToItem(null, 0, 0).y + node.height / 2 : node.mapToItem(null, 0, 0).x + node.width / 2
break;
case "bottom":
opt.offset = node.mapToItem(null, 0, 0).y + node.height
break;
case "right":
opt.offset = node.mapToItem(null, 0, 0).x + node.width
break;
}
}
var options = getOpts({
offset: opt.horizontal ? node.mapToItem(null, 0, 0).y : node.mapToItem(null, 0, 0).x,
horizontal: false
}, opt);
ruler.createObject(root, options);
break
case "padding":
// Show padding around an object
var options = getOpts({
padding: opt.padding
}, opt);
padding.createObject(root, {item: node, padding: options.padding});
break
case "brace":
// Create a brace between two objects
brace.createObject(root, {"from": node, "to": opt.to.nodes[0], "text": opt.text, "center": opt.center, "horizontal": opt.horizontal});
break
case "messure":
// Messure distance between two objects
messure.createObject(root, {"from": node, "to": opt.to.nodes[0], "type": opt.type});
break
}
}
/**
* Selector for qml elements
*/
function Select(str) {
// TODO support more complex syntax
// - multiple nodenames, hirachy, ...
if (str.search(/\{/) !== -1) {
this.nodeName = str.substring(0, str.indexOf("{"));
var members = str.match(/\{.+\}/);
try {
this.attrs = JSON.parse(members[0]);
}
catch(e) {
console.log("Could not parse attributes");
console.log(e);
}
}
else {
this.nodeName = str;
}
}
/**
* Check if the node matches the selector
*/
Select.prototype.match = function(node) {
if (this.nodeName === "*" || getClassName(node) === this.nodeName) {
if (typeof this.attrs !== "undefined") {
// TODO only return true if all attributes match
for (var attr in this.attrs) {
if (typeof node[attr] !== "undefined" && node[attr].toString() === this.attrs[attr]) {
return true;
}
}
}
else {
return true;
}
}
return false;
}
diff --git a/HIG/source/qml/lib/tools.js b/HIG/source/qml/lib/tools.js
index 4f6ea18..f853d9b 100644
--- a/HIG/source/qml/lib/tools.js
+++ b/HIG/source/qml/lib/tools.js
@@ -1,9 +1,52 @@
// get scale because e.g. annotation should not be scaled
function getScale(node) {
var scale = 1
while (node !== null) {
scale = scale * node.scale
node = node.parent
}
return scale;
}
+
+ function Timer() {
+ return Qt.createQmlObject("import QtQuick 2.2; Timer {}", root);
+}
+
+function sleep(delayTime, cb) {
+ var timer = new Timer();
+ timer.interval = delayTime;
+ timer.repeat = false;
+ timer.triggered.connect(cb);
+ timer.start();
+}
+
+function JoinSignals(signals, cb) {
+ this.signals = [];
+ this.cb = cb;
+ for (var i = 0; i < signals.length; i++) {
+ this.signals.push(new Signal(signals[i], this));
+ }
+}
+
+JoinSignals.prototype.check = function() {
+ for (var i = 0; i < this.signals.length; i++) {
+ if (!this.signals[i].fired) {
+ return;
+ }
+ }
+ this.cb();
+}
+
+function Signal(signal, join) {
+ this.fired = false;
+ var that = this;
+
+ signal.connect(function() {
+ that.fired = true;
+ join.check();
+ });
+}
+
+function join(signals, cb) {
+ var join = new JoinSignals(signals, cb);
+}
diff --git a/HIG/source/qml/models/Files.qml b/HIG/source/qml/models/Files.qml
index 64a5d9d..863833e 100644
--- a/HIG/source/qml/models/Files.qml
+++ b/HIG/source/qml/models/Files.qml
@@ -1,105 +1,105 @@
/*
* Copyright 2018 Fabian Riethmayer
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import QtQuick 2.6
ListModel {
id: model
// Pattern
ListElement {
name: ""
icon: ""
subfolder: [
ListElement {
name: ""
icon: ""
subfolder: ListElement {
name: ""
icon: ""
subfolder: [
ListElement {
name: ""
icon: ""
subfolder: ListElement {
name: ""
icon: ""
}
}
]
}
}
]
}
Component.onCompleted: {
model.clear()
var data = [{
"name": "HIG",
"icon": "folder-development",
"subfolder": [{
"name": "build",
- "icon": "folder-blue"
+ "icon": "folder"
}, {
"name": "source",
"icon": "folder-development",
"subfolder": [{
"name": "components",
"icon": "folder-text"
}, {
"name": "img",
"icon": "folder-picture"
}, {
"name": "introduction",
"icon": "folder-text"
}, {
"name": "layout",
"icon": "folder-text"
}, {
"name": "patterns",
"icon": "folder-text"
}, {
"name": "qml",
- "icon": "folder-blue",
+ "icon": "folder",
"subfolder": [{
"name": "ui",
"icon": "folder-text"
}, {
"name": "lib",
"icon": "folder-text"
}, {
"name": "models",
"icon": "folder-text"
}]
}, {
"name": "resources",
"icon": "folder-text"
}, {
"name": "style",
- "icon": "folder-blue"
+ "icon": "folder"
}, {
"name": "video",
"icon": "folder-video"
}]
}]
}]
model.insert(0, data)
}
}