diff --git a/src/qml/BookmarkList.qml b/src/qml/BookmarkList.qml
index 9edcd32389..44d8cbbd94 100644
--- a/src/qml/BookmarkList.qml
+++ b/src/qml/BookmarkList.qml
@@ -10,68 +10,27 @@ import Theme
/**
* \ingroup qml
*/
-Pane {
+QfPaneDrawer {
id: bookmarkList
property alias model: bookmarksList.model
property bool multiSelection: false
- property bool fullScreenView: false
- property bool isVertical: parent.width < parent.height || parent.width < 300
- property bool isDragging: false
- property real dragHeightAdjustment: 0
- property real dragWidthAdjustment: 0
- property real lastWidth
-
- width: {
- if (props.isVisible) {
- if (dragWidthAdjustment != 0) {
- return lastWidth - dragWidthAdjustment;
- } else if (fullScreenView || parent.width <= parent.height || width >= 0.95 * parent.width) {
- lastWidth = parent.width;
- return parent.width;
- } else {
- const newWidth = Math.min(Math.max(200, parent.width / 2.25), parent.width);
- lastWidth = newWidth;
- return newWidth;
- }
- } else {
- lastWidth = 0;
- return 0;
- }
- }
- property real lastHeight
-
- height: {
- if (props.isVisible) {
- if (dragHeightAdjustment != 0) {
- return Math.min(lastHeight - dragHeightAdjustment, parent.height - mainWindow.sceneTopMargin);
- } else if (fullScreenView || parent.width > parent.height || height >= 0.95 * parent.height) {
- lastHeight = parent.height;
- return parent.height;
- } else {
- const defaultMin = Math.min(Math.max(200, parent.height / 2), parent.height);
- const minContentHeight = bookmarkListToolBar.height + (bookmarksList.contentHeight + bookmarksList.anchors.bottomMargin) + 25;
- const newHeight = Math.min(minContentHeight, defaultMin);
- lastHeight = newHeight;
- return newHeight;
- }
- } else {
- lastHeight = 0;
- return 0;
- }
- }
- topPadding: 0
- leftPadding: 0
- rightPadding: 0
- bottomPadding: 0
+ contentVisible: props.isVisible
+ freezeKey: 'bookmarkresize'
+ headerHeight: bookmarkListToolBar.height
+ minContentHeight: bookmarkListToolBar.height + (bookmarksList.contentHeight + bookmarksList.anchors.bottomMargin) + 25
- visible: props.isVisible
- clip: true
+ onCollapsed: bookmarkList.hide()
- WheelHandler {
- acceptedDevices: PointerDevice.AllDevices
- onWheel: {}
- }
+ states: [
+ State {
+ name: "Hidden"
+ },
+ State {
+ name: "Visible"
+ }
+ ]
+ state: "Hidden"
QtObject {
id: props
@@ -443,50 +402,6 @@ Pane {
}
}
- function setMultiSelection(active) {
- multiSelection = active;
- if (model) {
- model.hideProjectBookmarks = active;
- }
- }
-
- function statusIndicatorDragged(deltaX, deltaY) {
- fullScreenView = false;
- if (isVertical) {
- dragHeightAdjustment += deltaY;
- } else {
- dragWidthAdjustment += deltaX;
- }
- }
-
- function statusIndicatorDragReleased() {
- isDragging = false;
- if (isVertical) {
- const minContentHeight = bookmarkListToolBar.height + 48 + 30;
- if (bookmarkList.height < minContentHeight) {
- if (fullScreenView) {
- fullScreenView = false;
- } else {
- bookmarkList.hide();
- }
- } else if (dragHeightAdjustment < -parent.height * 0.2) {
- fullScreenView = true;
- }
- } else {
- if (bookmarkList.width < bookmarkList.parent.width * 0.3) {
- if (fullScreenView) {
- fullScreenView = false;
- } else {
- bookmarkList.hide();
- }
- } else if (dragWidthAdjustment < -parent.width * 0.2) {
- fullScreenView = true;
- }
- }
- dragHeightAdjustment = 0;
- dragWidthAdjustment = 0;
- }
-
Keys.onReleased: event => {
if (event.key === Qt.Key_Back || event.key === Qt.Key_Escape) {
if (Overlay.overlay && Overlay.overlay.visibleChildren.length > 1 || (Overlay.overlay.visibleChildren.length === 1 && !toast.visible)) {
@@ -502,39 +417,17 @@ Pane {
}
}
- Behavior on width {
- enabled: !isDragging
- PropertyAnimation {
- duration: parent.width > parent.height ? 250 : 0
- easing.type: Easing.OutQuart
-
- onRunningChanged: {
- if (running)
- mapCanvasMap.freeze('bookmarkresize');
- else
- mapCanvasMap.unfreeze('bookmarkresize');
- }
- }
- }
-
- Behavior on height {
- enabled: !isDragging
- PropertyAnimation {
- duration: parent.width < parent.height ? 250 : 0
- easing.type: Easing.OutQuart
-
- onRunningChanged: {
- if (running)
- mapCanvasMap.freeze('bookmarkresize');
- else
- mapCanvasMap.unfreeze('bookmarkresize');
- }
- }
- }
-
function show() {
props.isVisible = true;
focus = true;
+ state = "Visible";
+ }
+
+ function setMultiSelection(active) {
+ multiSelection = active;
+ if (model) {
+ model.hideProjectBookmarks = active;
+ }
}
function hide() {
@@ -545,5 +438,6 @@ Pane {
if (bookmarkList.model) {
bookmarkList.model.clearSelection();
}
+ state = "Hidden";
}
}
diff --git a/src/qml/FeatureListForm.qml b/src/qml/FeatureListForm.qml
index 648b79bcea..8199d99ba9 100644
--- a/src/qml/FeatureListForm.qml
+++ b/src/qml/FeatureListForm.qml
@@ -26,7 +26,7 @@ import Theme
/**
* \ingroup qml
*/
-Pane {
+QfPaneDrawer {
id: featureFormList
property ProcessingAlgorithm algorithm: processingAlgorithm
@@ -49,15 +49,22 @@ Pane {
property bool allowDelete
property bool multiSelection: false
- property bool fullScreenView: qfieldSettings.fullScreenIdentifyView
- property bool isVertical: parent.width < parent.height || parent.width < 300
-
- property bool isDragging: false
- property real dragHeightAdjustment: 0
- property real dragWidthAdjustment: 0
+ fullScreenView: qfieldSettings.fullScreenIdentifyView
property bool canvasOperationRequested: digitizingToolbar.geometryRequested || moveFeaturesToolbar.moveFeaturesRequested || rotateFeaturesToolbar.rotateFeaturesRequested
+ contentVisible: props.isVisible || featureFormList.canvasOperationRequested
+ freezeKey: 'formresize'
+ headerHeight: featureListToolBar.height
+ useDefaultMinHeight: featureFormList.state !== "FeatureList"
+ minContentHeight: featureListToolBar.height + (globalFeaturesList.contentHeight + globalFeaturesList.anchors.bottomMargin) + 25
+
+ onCollapsed: {
+ if (featureFormList.state !== 'FeatureFormEdit') {
+ featureFormList.state = 'Hidden';
+ }
+ }
+
signal showMessage(string message)
signal editGeometry
signal requestJumpToPoint(var center, real scale, bool handleMargins)
@@ -66,58 +73,11 @@ Pane {
featureForm.requestCancel();
}
- property real lastWidth
-
- width: {
- if (props.isVisible || featureFormList.canvasOperationRequested) {
- if (dragWidthAdjustment != 0) {
- return lastWidth - dragWidthAdjustment;
- } else if (fullScreenView || parent.width <= parent.height || width >= 0.95 * parent.width) {
- lastWidth = parent.width;
- return parent.width;
- } else {
- const newWidth = Math.min(Math.max(200, parent.width / 2.25), parent.width);
- lastWidth = newWidth;
- return newWidth;
- }
- } else {
- lastWidth = 0;
- return 0;
- }
- }
- property real lastHeight
-
- height: {
- if (props.isVisible || featureFormList.canvasOperationRequested) {
- if (dragHeightAdjustment != 0) {
- return Math.min(lastHeight - dragHeightAdjustment, parent.height - mainWindow.sceneTopMargin);
- } else if (fullScreenView || parent.width > parent.height || height >= 0.95 * parent.height) {
- lastHeight = parent.height;
- return parent.height;
- } else {
- const defaultMin = Math.min(Math.max(200, parent.height / 2), parent.height);
- var minContentHeight = featureFormList.state !== "FeatureList" ? defaultMin : featureListToolBar.height + (globalFeaturesList.contentHeight + globalFeaturesList.anchors.bottomMargin) + 25;
- const newHeight = Math.min(minContentHeight, defaultMin);
- lastHeight = newHeight;
- return newHeight;
- }
- } else {
- lastHeight = 0;
- return 0;
- }
- }
-
anchors.bottomMargin: featureFormList.canvasOperationRequested ? featureFormList.height : 0
anchors.rightMargin: featureFormList.canvasOperationRequested ? -featureFormList.width : 0
opacity: featureFormList.canvasOperationRequested ? 0.5 : 1
- topPadding: 0
- leftPadding: 0
- rightPadding: 0
- bottomPadding: 0
-
enabled: !featureFormList.canvasOperationRequested
- visible: props.isVisible
states: [
State {
@@ -255,12 +215,6 @@ Pane {
}
]
state: "Hidden"
- clip: true
-
- WheelHandler {
- acceptedDevices: PointerDevice.AllDevices
- onWheel: {}
- }
QtObject {
id: props
@@ -560,48 +514,15 @@ Pane {
}
onStatusIndicatorDragged: function (deltaX, deltaY) {
- fullScreenView = false;
- if (isVertical) {
- dragHeightAdjustment += deltaY;
- } else {
- dragWidthAdjustment += deltaX;
- }
+ featureFormList.statusIndicatorDragged(deltaX, deltaY);
}
onStatusIndicatorDragAcquired: {
- isDragging = true;
+ featureFormList.isDragging = true;
}
onStatusIndicatorDragReleased: {
- isDragging = false;
- if (isVertical) {
- const minContentHeight = featureListToolBar.height + 48 + 30;
- if (featureFormList.height < minContentHeight) {
- if (fullScreenView) {
- fullScreenView = false;
- } else {
- if (featureFormList.state !== 'FeatureFormEdit') {
- featureFormList.state = 'Hidden';
- }
- }
- } else if (dragHeightAdjustment < -parent.height * 0.2) {
- fullScreenView = true;
- }
- } else {
- if (featureFormList.width < featureFormList.parent.width * 0.3) {
- if (fullScreenView) {
- fullScreenView = false;
- } else {
- if (featureFormList.state != 'FeatureFormEdit') {
- featureFormList.state = 'Hidden';
- }
- }
- } else if (dragWidthAdjustment < -parent.width * 0.2) {
- fullScreenView = true;
- }
- }
- dragHeightAdjustment = 0;
- dragWidthAdjustment = 0;
+ featureFormList.statusIndicatorDragReleased();
}
onEditAttributesButtonClicked: {
@@ -806,36 +727,6 @@ Pane {
}
}
- Behavior on width {
- enabled: !isDragging
- PropertyAnimation {
- duration: parent.width > parent.height ? 250 : 0
- easing.type: Easing.OutQuart
-
- onRunningChanged: {
- if (running)
- mapCanvasMap.freeze('formresize');
- else
- mapCanvasMap.unfreeze('formresize');
- }
- }
- }
-
- Behavior on height {
- enabled: !isDragging
- PropertyAnimation {
- duration: parent.width < parent.height ? 250 : 0
- easing.type: Easing.OutQuart
-
- onRunningChanged: {
- if (running)
- mapCanvasMap.freeze('formresize');
- else
- mapCanvasMap.unfreeze('formresize');
- }
- }
- }
-
Behavior on anchors.rightMargin {
PropertyAnimation {
duration: 250
diff --git a/src/qml/imports/Theme/QfPaneDrawer.qml b/src/qml/imports/Theme/QfPaneDrawer.qml
new file mode 100644
index 0000000000..ef07afd723
--- /dev/null
+++ b/src/qml/imports/Theme/QfPaneDrawer.qml
@@ -0,0 +1,158 @@
+import QtQuick
+import QtQuick.Controls
+
+/**
+ * \ingroup qml
+ */
+Pane {
+ id: paneDrawer
+
+ //! TRUE when the pane is laid out vertically (portrait or narrow), driving the drag axis and resize animation direction
+ readonly property bool isVertical: parent.width < parent.height || parent.width < 300
+ //! When TRUE the pane expands to fill the whole available area
+ property bool fullScreenView: false
+ //! TRUE while the header is being dragged to resize the pane
+ property bool isDragging: false
+
+ //! When TRUE the pane is laid out at its resting size, when FALSE it collapses to zero
+ property bool contentVisible: false
+ //! Content driven minimum height the pane snaps to at rest, clamped to half the available height
+ property real minContentHeight: 0
+ //! When TRUE the resting height ignores a minContentHeight and uses the default minimum
+ property bool useDefaultMinHeight: false
+ //! Height of the header, used to compute the collapse threshold
+ property real headerHeight: 0
+ //! Key passed to mapCanvasMap freeze/unfreeze so concurrent panes does not clear each other
+ property string freezeKey
+ //! Emitted when a drag releases below the minimum size without entering fullscreen
+ signal collapsed
+
+ //! Internal state driving the resize math, kept out of the public interface
+ QtObject {
+ id: props
+
+ property real dragHeightAdjustment: 0
+ property real dragWidthAdjustment: 0
+ property real lastWidth
+ property real lastHeight
+ }
+
+ width: {
+ if (contentVisible) {
+ if (props.dragWidthAdjustment != 0) {
+ return props.lastWidth - props.dragWidthAdjustment;
+ } else if (fullScreenView || parent.width <= parent.height || width >= 0.95 * parent.width) {
+ props.lastWidth = parent.width;
+ return parent.width;
+ } else {
+ const newWidth = Math.min(Math.max(200, parent.width / 2.25), parent.width);
+ props.lastWidth = newWidth;
+ return newWidth;
+ }
+ } else {
+ props.lastWidth = 0;
+ return 0;
+ }
+ }
+
+ height: {
+ if (contentVisible) {
+ if (props.dragHeightAdjustment != 0) {
+ return Math.min(props.lastHeight - props.dragHeightAdjustment, parent.height - mainWindow.sceneTopMargin);
+ } else if (fullScreenView || parent.width > parent.height || height >= 0.95 * parent.height) {
+ props.lastHeight = parent.height;
+ return parent.height;
+ } else {
+ const defaultMin = Math.min(Math.max(200, parent.height / 2), parent.height);
+ const newHeight = useDefaultMinHeight ? defaultMin : Math.min(minContentHeight, defaultMin);
+ props.lastHeight = newHeight;
+ return newHeight;
+ }
+ } else {
+ props.lastHeight = 0;
+ return 0;
+ }
+ }
+
+ topPadding: 0
+ leftPadding: 0
+ rightPadding: 0
+ bottomPadding: 0
+
+ visible: contentVisible
+ clip: true
+
+ WheelHandler {
+ acceptedDevices: PointerDevice.AllDevices
+ onWheel: {}
+ }
+
+ function statusIndicatorDragged(deltaX, deltaY) {
+ fullScreenView = false;
+ if (isVertical) {
+ props.dragHeightAdjustment += deltaY;
+ } else {
+ props.dragWidthAdjustment += deltaX;
+ }
+ }
+
+ function statusIndicatorDragReleased() {
+ isDragging = false;
+ if (isVertical) {
+ const minHeight = headerHeight + 48 + 30;
+ if (paneDrawer.height < minHeight) {
+ if (fullScreenView) {
+ fullScreenView = false;
+ } else {
+ paneDrawer.collapsed();
+ }
+ } else if (props.dragHeightAdjustment < -parent.height * 0.2) {
+ fullScreenView = true;
+ }
+ } else {
+ if (paneDrawer.width < paneDrawer.parent.width * 0.3) {
+ if (fullScreenView) {
+ fullScreenView = false;
+ } else {
+ paneDrawer.collapsed();
+ }
+ } else if (props.dragWidthAdjustment < -parent.width * 0.2) {
+ fullScreenView = true;
+ }
+ }
+ props.dragHeightAdjustment = 0;
+ props.dragWidthAdjustment = 0;
+ }
+
+ Behavior on width {
+ enabled: !isDragging
+ PropertyAnimation {
+ duration: paneDrawer.parent.width > paneDrawer.parent.height ? 250 : 0
+ easing.type: Easing.OutQuart
+
+ onRunningChanged: {
+ if (running) {
+ mapCanvasMap.freeze(paneDrawer.freezeKey);
+ } else {
+ mapCanvasMap.unfreeze(paneDrawer.freezeKey);
+ }
+ }
+ }
+ }
+
+ Behavior on height {
+ enabled: !isDragging
+ PropertyAnimation {
+ duration: paneDrawer.parent.width < paneDrawer.parent.height ? 250 : 0
+ easing.type: Easing.OutQuart
+
+ onRunningChanged: {
+ if (running) {
+ mapCanvasMap.freeze(paneDrawer.freezeKey);
+ } else {
+ mapCanvasMap.unfreeze(paneDrawer.freezeKey);
+ }
+ }
+ }
+ }
+}
diff --git a/src/qml/imports/Theme/qmldir b/src/qml/imports/Theme/qmldir
index 650e3a2903..9264d3dcb4 100644
--- a/src/qml/imports/Theme/qmldir
+++ b/src/qml/imports/Theme/qmldir
@@ -13,6 +13,7 @@ QfMeterBar 1.0 QfMeterBar.qml
QfOpacityMask 1.0 QfOpacityMask.qml
QfOverlayContainer 1.0 QfOverlayContainer.qml
QfPageHeader 1.0 QfPageHeader.qml
+QfPaneDrawer 1.0 QfPaneDrawer.qml
QfPopup 1.0 QfPopup.qml
QfProgressRing 1.0 QfProgressRing.qml
QfProjectThumbnail 1.0 QfProjectThumbnail.qml
diff --git a/src/qml/qgismobileapp.qml b/src/qml/qgismobileapp.qml
index 7934627fb5..d4bb48eb45 100644
--- a/src/qml/qgismobileapp.qml
+++ b/src/qml/qgismobileapp.qml
@@ -4659,8 +4659,8 @@ ApplicationWindow {
bottom: parent.bottom
}
- onVisibleChanged: {
- if (visible && featureListForm.visible) {
+ onStateChanged: {
+ if (state !== "Hidden" && featureListForm.visible) {
featureListForm.hide();
}
}
diff --git a/src/qml/qml.qrc b/src/qml/qml.qrc
index 7321fbc207..4081eba302 100644
--- a/src/qml/qml.qrc
+++ b/src/qml/qml.qrc
@@ -109,19 +109,20 @@
Nyuki.qml
LayerLoginDialog.qml
imports/Theme/QfActionButton.qml
+ imports/Theme/QfButton.qml
imports/Theme/QfComboBox.qml
imports/Theme/QfDropShadow.qml
imports/Theme/QfExpandableGroupBox.qml
imports/Theme/QfOpacityMask.qml
imports/Theme/QfToolButton.qml
imports/Theme/QfToolButtonDrawer.qml
- imports/Theme/QfButton.qml
imports/Theme/QfSwitch.qml
imports/Theme/QfTextField.qml
imports/Theme/QfCollapsibleMessage.qml
imports/Theme/QfSlider.qml
imports/Theme/QfCalendarPanel.qml
imports/Theme/QfPageHeader.qml
+ imports/Theme/QfPaneDrawer.qml
imports/Theme/QfOverlayContainer.qml
imports/Theme/QfTabBar.qml
imports/Theme/qmldir