Commit fec8764d authored by Noah Davis's avatar Noah Davis 🌵
Browse files

Add OverviewControl

Functions much like the birds eye/overview control in Gwenview.

A few differences:

- You can click outside of the handle to instantly jump to a location.
- The handle has a dot on it for visibility at small sizes.
- The mouse cursor changes to an open or closed hand when you hover over
or grab the handle.
parent 7f7d241d
/* SPDX-FileCopyrightText: 2021 Noah Davis <noahadvs@gmail.com>
* SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
*/
import QtQuick 2.15
import QtQml 2.15
import org.kde.kirigami 2.15 as Kirigami
Rectangle {
id: root
property Item target: null
property alias pressed: mouseArea.pressed
property real contentAspectRatio: target ? target.mediaAspectRatio : 1
property real widthRatio: target ? target.width / target.contentWidth : 1
property real heightRatio: target ? target.height / target.contentHeight : 1
// Don't use Flickable::visibleArea.xPosition or Flickable::visibleArea.yPosition. They won't give the correct values.
property real normalizedX: target && (target.contentWidth - target.width) !== 0 ?
-target.contentX / (target.contentWidth - target.width) : 0
property real normalizedY: target && (target.contentHeight - target.height) !== 0 ?
-target.contentY / (target.contentHeight - target.height) : 0
readonly property real preferredWidth: contentAspectRatio >= 1 || contentAspectRatio <= 0 ?
implicitWidth : implicitHeight * contentAspectRatio
readonly property real preferredHeight: contentAspectRatio <= 1 ?
implicitHeight : implicitWidth / contentAspectRatio
implicitWidth: 100
implicitHeight: 100
width: preferredWidth
height: preferredHeight
color: Qt.rgba(0,0,0,0.5)
border.color: Qt.rgba(1,1,1,1)
border.width: 1
antialiasing: false // no need for rounding now
Rectangle {
id: handleRect
property bool mouseInside: mouseArea.mouseX >= handleRect.x
&& mouseArea.mouseX <= handleRect.x + handleRect.width
&& mouseArea.mouseY >= handleRect.y
&& mouseArea.mouseY <= handleRect.y + handleRect.height
visible: Math.max(width, height) > dot.implicitHeight
antialiasing: false
width: Math.min(root.width * root.widthRatio, root.width)
height: Math.min(root.height * root.heightRatio, root.height)
color: Qt.rgba(1,1,1,0.25)
border.color: Qt.rgba(1,1,1,0.5)
border.width: 1
Binding {
target: handleRect; property: "x"
value: root.normalizedX * (root.width - handleRect.width)
when: !mouseArea.pressed
restoreMode: Binding.RestoreBinding
}
Binding {
target: handleRect; property: "y"
value: root.normalizedY * (root.height - handleRect.height)
when: !mouseArea.pressed
restoreMode: Binding.RestoreBinding
}
}
Rectangle {
id: dot // For improved visibility
radius: height / 2
anchors.centerIn: handleRect
implicitWidth: 6
implicitHeight: 6
color: "white"
// shadow outline for slightly better contrast.
// Even more contrast when handle is too small.
border.color: Qt.rgba(0, 0, 0,
handleRect.width - 2 <= dot.implicitWidth
|| handleRect.height - 2 <= dot.implicitHeight ? 0.4 : 0.2)
border.width: 1
Behavior on border.color {
ColorAnimation {
duration: Kirigami.Units.shortDuration
// No easing curve looks better since the motion between larger
// and smaller handle sizes tends to look fairly linear.
}
}
}
MouseArea {
id: mouseArea
anchors.fill: parent
hoverEnabled: true
cursorShape: if (pressed) {
return Qt.ClosedHandCursor
} else if (handleRect.mouseInside) {
return Qt.OpenHandCursor
} else {
return Qt.ArrowCursor
}
preventStealing: true
drag {
axis: Drag.XAndYAxis
target: handleRect
minimumX: 0
maximumX: root.width - handleRect.width
minimumY: 0
maximumY: root.height - handleRect.height
threshold: 0
}
onPressed: if (!handleRect.mouseInside && !mouseArea.drag.active) {
handleRect.x = Math.max(drag.minimumX, // min
Math.min(mouseArea.mouseX - handleRect.width / 2,
drag.maximumX)) // max
handleRect.y = Math.max(drag.minimumY, // min
Math.min(mouseArea.mouseY - handleRect.height / 2,
drag.maximumY)) // max
}
}
Binding {
target: root; property: "normalizedX"
value: handleRect.x / (root.width - handleRect.width)
when: mouseArea.pressed
restoreMode: Binding.RestoreBinding
}
Binding {
target: root; property: "normalizedY"
value: handleRect.y / (root.height - handleRect.height)
when: mouseArea.pressed
restoreMode: Binding.RestoreBinding
}
}
......@@ -10,6 +10,7 @@ SPDX-License-Identifier: LGPL-2.0-or-later
<file>qml/ImageDelegate.qml</file>
<file>qml/ImageViewer.qml</file>
<file>qml/Main.qml</file>
<file>qml/OverviewControl.qml</file>
<file>qml/SelectionButton.qml</file>
<file>qml/SelectionDelegateHighlight.qml</file>
<file>qml/ShareDialog.qml</file>
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment