diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 9dd1168135..ebe97bb0f2 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -23,6 +23,7 @@ from UM.Platform import Platform from UM.PluginError import PluginNotFoundError from UM.Resources import Resources from UM.Preferences import Preferences +from UM.Qt.Bindings import MainWindow from UM.Qt.QtApplication import QtApplication # The class we're inheriting from. import UM.Util from UM.View.SelectionPass import SelectionPass # For typing. @@ -522,6 +523,10 @@ class CuraApplication(QtApplication): preferences.addPreference("cura/use_multi_build_plate", False) preferences.addPreference("view/settings_list_height", 400) preferences.addPreference("view/settings_visible", False) + preferences.addPreference("view/settings_xpos", 0) + preferences.addPreference("view/settings_ypos", 56) + preferences.addPreference("view/colorscheme_xpos", 0) + preferences.addPreference("view/colorscheme_ypos", 56) preferences.addPreference("cura/currency", "€") preferences.addPreference("cura/material_settings", "{}") @@ -1782,3 +1787,19 @@ class CuraApplication(QtApplication): # Only show the what's new dialog if there's no machine and we have just upgraded show_whatsnew_only = has_active_machine and has_app_just_upgraded return show_whatsnew_only + + @pyqtSlot(result = int) + def appWidth(self) -> int: + main_window = QtApplication.getInstance().getMainWindow() + if main_window: + return main_window.width() + else: + return 0 + + @pyqtSlot(result = int) + def appHeight(self) -> int: + main_window = QtApplication.getInstance().getMainWindow() + if main_window: + return main_window.height() + else: + return 0 diff --git a/plugins/PrepareStage/PrepareMenu.qml b/plugins/PrepareStage/PrepareMenu.qml index d8953d7661..87d7c5f35c 100644 --- a/plugins/PrepareStage/PrepareMenu.qml +++ b/plugins/PrepareStage/PrepareMenu.qml @@ -20,11 +20,19 @@ Item name: "cura" } + anchors + { + left: parent.left + right: parent.right + leftMargin: UM.Theme.getSize("wide_margin").width + rightMargin: UM.Theme.getSize("wide_margin").width + } + // Item to ensure that all of the buttons are nicely centered. Item { anchors.horizontalCenter: parent.horizontalCenter - width: openFileButton.width + itemRow.width + UM.Theme.getSize("default_margin").width + width: parent.width - 2 * UM.Theme.getSize("wide_margin").width height: parent.height RowLayout @@ -32,9 +40,9 @@ Item id: itemRow anchors.left: openFileButton.right + anchors.right: parent.right anchors.leftMargin: UM.Theme.getSize("default_margin").width - width: Math.round(0.9 * prepareMenu.width) height: parent.height spacing: 0 diff --git a/plugins/PreviewStage/PreviewMenu.qml b/plugins/PreviewStage/PreviewMenu.qml index 62f814aac9..ff1ccff75f 100644 --- a/plugins/PreviewStage/PreviewMenu.qml +++ b/plugins/PreviewStage/PreviewMenu.qml @@ -20,15 +20,21 @@ Item name: "cura" } + anchors + { + left: parent.left + right: parent.right + leftMargin: UM.Theme.getSize("wide_margin").width + rightMargin: UM.Theme.getSize("wide_margin").width + } + Row { id: stageMenuRow - anchors.centerIn: parent - height: parent.height - width: childrenRect.width - // We want this row to have a preferred with equals to the 85% of the parent - property int preferredWidth: Math.round(0.85 * previewMenu.width) + anchors.horizontalCenter: parent.horizontalCenter + width: parent.width - 2 * UM.Theme.getSize("wide_margin").width + height: parent.height Cura.ViewsSelector { @@ -49,12 +55,12 @@ Item color: UM.Theme.getColor("lining") } - // This component will grow freely up to complete the preferredWidth of the row. + // This component will grow freely up to complete the width of the row. Loader { id: viewPanel height: parent.height - width: source != "" ? (stageMenuRow.preferredWidth - viewsSelector.width - printSetupSelectorItem.width - 2 * UM.Theme.getSize("default_lining").width) : 0 + width: source != "" ? (previewMenu.width - viewsSelector.width - printSetupSelectorItem.width - 2 * (UM.Theme.getSize("wide_margin").width + UM.Theme.getSize("default_lining").width)) : 0 source: UM.Controller.activeView != null && UM.Controller.activeView.stageMenuComponent != null ? UM.Controller.activeView.stageMenuComponent : "" } diff --git a/plugins/SimulationView/SimulationViewMenuComponent.qml b/plugins/SimulationView/SimulationViewMenuComponent.qml index 6a035cc624..b94cf029f0 100644 --- a/plugins/SimulationView/SimulationViewMenuComponent.qml +++ b/plugins/SimulationView/SimulationViewMenuComponent.qml @@ -15,6 +15,8 @@ Cura.ExpandableComponent { id: base + dragPreferencesNamePrefix: "view/colorscheme" + contentHeaderTitle: catalog.i18nc("@label", "Color scheme") Connections diff --git a/resources/qml/ExpandableComponent.qml b/resources/qml/ExpandableComponent.qml index 025c63d754..53f9f85341 100644 --- a/resources/qml/ExpandableComponent.qml +++ b/resources/qml/ExpandableComponent.qml @@ -78,11 +78,19 @@ Item property int shadowOffset: 2 + // Prefix used for the dragged position preferences. Preferences not used if empty. Don't translate! + property string dragPreferencesNamePrefix: "" + function toggleContent() { contentContainer.visible = !expanded } + function updateDragPosition() + { + contentContainer.trySetPosition(contentContainer.x, contentContainer.y); + } + // Add this binding since the background color is not updated otherwise Binding { @@ -102,7 +110,8 @@ Item { if (!base.enabled && expanded) { - toggleContent() + toggleContent(); + updateDragPosition(); } } } @@ -196,17 +205,19 @@ Item Cura.RoundedRectangle { id: contentContainer + property string dragPreferencesNameX: "_xpos" + property string dragPreferencesNameY: "_ypos" visible: false width: childrenRect.width height: childrenRect.height // Ensure that the content is located directly below the headerItem - y: background.height + base.shadowOffset + base.contentSpacingY + y: dragPreferencesNamePrefix === "" ? (background.height + base.shadowOffset + base.contentSpacingY) : UM.Preferences.getValue(dragPreferencesNamePrefix + dragPreferencesNameY) // Make the content aligned with the rest, using the property contentAlignment to decide whether is right or left. // In case of right alignment, the 3x padding is due to left, right and padding between the button & text. - x: contentAlignment == ExpandableComponent.ContentAlignment.AlignRight ? -width + collapseButton.width + headerItemLoader.width + 3 * background.padding : 0 + x: dragPreferencesNamePrefix === "" ? (contentAlignment == ExpandableComponent.ContentAlignment.AlignRight ? -width + collapseButton.width + headerItemLoader.width + 3 * background.padding : 0) : UM.Preferences.getValue(dragPreferencesNamePrefix + dragPreferencesNameX) cornerSide: Cura.RoundedRectangle.Direction.All color: contentBackgroundColor @@ -214,6 +225,25 @@ Item border.color: UM.Theme.getColor("lining") radius: UM.Theme.getSize("default_radius").width + function trySetPosition(posNewX, posNewY) + { + var margin = UM.Theme.getSize("narrow_margin"); + var minPt = base.mapFromItem(null, margin.width, margin.height); + var maxPt = base.mapFromItem(null, + CuraApplication.appWidth() - (contentContainer.width + margin.width), + CuraApplication.appHeight() - (contentContainer.height + margin.height)); + var initialY = background.height + base.shadowOffset + margin.height; + + contentContainer.x = Math.max(minPt.x, Math.min(maxPt.x, posNewX)); + contentContainer.y = Math.max(initialY, Math.min(maxPt.y, posNewY)); + + if (dragPreferencesNamePrefix !== "") + { + UM.Preferences.setValue(dragPreferencesNamePrefix + dragPreferencesNameX, contentContainer.x); + UM.Preferences.setValue(dragPreferencesNamePrefix + dragPreferencesNameY, contentContainer.y); + } + } + ExpandableComponentHeader { id: contentHeader @@ -225,6 +255,55 @@ Item left: parent.left } + MouseArea + { + id: dragRegion + anchors + { + top: parent.top + bottom: parent.bottom + left: parent.left + right: contentHeader.xPosCloseButton + } + property var clickPos: Qt.point(0, 0) + + onPressed: + { + clickPos = Qt.point(mouse.x, mouse.y); + } + + onPositionChanged: + { + var delta = Qt.point(mouse.x - clickPos.x, mouse.y - clickPos.y); + if (delta.x !== 0 || delta.y !== 0) + { + contentContainer.trySetPosition(contentContainer.x + delta.x, contentContainer.y + delta.y); + } + } + + onDoubleClicked: + { + contentContainer.trySetPosition(0, 0); + } + + Connections + { + target: UM.Preferences + onPreferenceChanged: + { + if + ( + preference !== "general/window_height" && + preference !== "general/window_width" && + preference !== "general/window_state" + ) + { + return; + } + contentContainer.trySetPosition(contentContainer.x, contentContainer.y); + } + } + } } Control diff --git a/resources/qml/ExpandableComponentHeader.qml b/resources/qml/ExpandableComponentHeader.qml index 94066340e3..cd6ccfb825 100644 --- a/resources/qml/ExpandableComponentHeader.qml +++ b/resources/qml/ExpandableComponentHeader.qml @@ -13,6 +13,7 @@ Cura.RoundedRectangle id: header property alias headerTitle: headerLabel.text + property alias xPosCloseButton: closeButton.left height: UM.Theme.getSize("expandable_component_content_header").height color: UM.Theme.getColor("secondary") diff --git a/resources/qml/PrintSetupSelector/PrintSetupSelector.qml b/resources/qml/PrintSetupSelector/PrintSetupSelector.qml index 48b6d191c2..1a9bd9f109 100644 --- a/resources/qml/PrintSetupSelector/PrintSetupSelector.qml +++ b/resources/qml/PrintSetupSelector/PrintSetupSelector.qml @@ -11,6 +11,8 @@ Cura.ExpandableComponent { id: printSetupSelector + dragPreferencesNamePrefix: "view/settings" + property bool preSlicedData: PrintInformation.preSliced contentPadding: UM.Theme.getSize("default_lining").width diff --git a/resources/qml/PrintSetupSelector/PrintSetupSelectorContents.qml b/resources/qml/PrintSetupSelector/PrintSetupSelectorContents.qml index 7da0e92bb9..3b090f7476 100644 --- a/resources/qml/PrintSetupSelector/PrintSetupSelectorContents.qml +++ b/resources/qml/PrintSetupSelector/PrintSetupSelectorContents.qml @@ -14,6 +14,8 @@ Item { id: content + property int absoluteMinimumHeight: 200 * screenScaleFactor + width: UM.Theme.getSize("print_setup_widget").width - 2 * UM.Theme.getSize("default_margin").width height: contents.height + buttonRow.height @@ -86,8 +88,14 @@ Item Math.min ( UM.Preferences.getValue("view/settings_list_height"), - base.height - (customPrintSetup.mapToItem(null, 0, 0).y + buttonRow.height + UM.Theme.getSize("default_margin").height) + Math.max + ( + absoluteMinimumHeight, + base.height - (customPrintSetup.mapToItem(null, 0, 0).y + buttonRow.height + UM.Theme.getSize("default_margin").height) + ) ); + + updateDragPosition(); } } visible: currentModeIndex == PrintSetupSelectorContents.Mode.Custom @@ -143,7 +151,11 @@ Item iconSource: UM.Theme.getIcon("arrow_right") isIconOnRightSide: true visible: currentModeIndex == PrintSetupSelectorContents.Mode.Recommended - onClicked: currentModeIndex = PrintSetupSelectorContents.Mode.Custom + onClicked: + { + currentModeIndex = PrintSetupSelectorContents.Mode.Custom + updateDragPosition(); + } } //Invisible area at the bottom with which you can resize the panel. @@ -171,9 +183,9 @@ Item // position of mouse relative to dropdown align vertical centre of mouse area to cursor // v------------------------------v v------------v var h = mouseY + buttonRow.y + content.y - height / 2 | 0; - if(h < 200 * screenScaleFactor) //Enforce a minimum size. + if(h < absoluteMinimumHeight) //Enforce a minimum size. { - h = 200 * screenScaleFactor; + h = absoluteMinimumHeight; } //Absolute mouse Y position in the window, to prevent it from going outside the window.