Format the slider for the infill in the recommended mode

Contributes to CURA-5941
This commit is contained in:
Diego Prado Gesto 2018-12-02 12:03:58 +01:00
parent 2c5f5170c2
commit 1238aa7304
4 changed files with 268 additions and 295 deletions

View file

@ -25,7 +25,7 @@ Item
{ {
id: header id: header
height: UM.Theme.getSize("print_setup_widget_header").height height: UM.Theme.getSize("print_setup_widget_header").height
color: "transparent" //UM.Theme.getColor("action_button_hovered") // TODO: It's not clear the color that we need to use here color: UM.Theme.getColor("action_button_hovered") // TODO: It's not clear the color that we need to use here
anchors anchors
{ {

View file

@ -15,57 +15,37 @@ import Cura 1.0 as Cura
Item Item
{ {
id: infillRow id: infillRow
height: childrenRect.height
property real labelColumnWidth: Math.round(width / 3)
// Here are the elements that are shown in the left column
Cura.IconWithText Cura.IconWithText
{ {
id: infillRowTitle id: infillRowTitle
source: UM.Theme.getIcon("category_infill") source: UM.Theme.getIcon("category_infill")
text: catalog.i18nc("@label", "Infill") + " (%)" text: catalog.i18nc("@label", "Infill") + " (%)"
anchors.bottom: parent.bottom
width: labelColumnWidth width: labelColumnWidth
} }
Item Item
{ {
id: infillCellRight id: infillSliderContainer
height: childrenRect.height
height: infillSlider.height + UM.Theme.getSize("thick_margin").height + enableGradualInfillCheckBox.visible * (enableGradualInfillCheckBox.height + UM.Theme.getSize("thick_margin").height) anchors
anchors.left: infillRowTitle.right
anchors.right: parent.right
Label
{ {
id: selectedInfillRateText left: infillRowTitle.right
right: parent.right
anchors.left: infillSlider.left verticalCenter: infillRowTitle.verticalCenter
anchors.right: parent.right
text: parseInt(infillDensity.properties.value) + "%"
horizontalAlignment: Text.AlignLeft
color: infillSlider.enabled ? UM.Theme.getColor("quality_slider_available") : UM.Theme.getColor("quality_slider_unavailable")
}
// We use a binding to make sure that after manually setting infillSlider.value it is still bound to the property provider
Binding
{
target: infillSlider
property: "value"
value: parseInt(infillDensity.properties.value)
} }
Slider Slider
{ {
id: infillSlider id: infillSlider
anchors.top: selectedInfillRateText.bottom width: parent.width
anchors.left: parent.left height: UM.Theme.getSize("print_setup_slider_handle").height // The handle is the widest element of the slider
anchors.right: infillIcon.left
anchors.rightMargin: UM.Theme.getSize("thick_margin").width
height: UM.Theme.getSize("thick_margin").height
width: parseInt(infillCellRight.width - UM.Theme.getSize("thick_margin").width - style.handleWidth)
minimumValue: 0 minimumValue: 0
maximumValue: 100 maximumValue: 100
@ -78,9 +58,62 @@ Item
// set initial value from stack // set initial value from stack
value: parseInt(infillDensity.properties.value) value: parseInt(infillDensity.properties.value)
style: SliderStyle
{
//Draw line
groove: Item
{
Rectangle
{
height: UM.Theme.getSize("print_setup_slider_groove").height
width: control.width - UM.Theme.getSize("print_setup_slider_handle").width
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
color: control.enabled ? UM.Theme.getColor("quality_slider_available") : UM.Theme.getColor("quality_slider_unavailable")
}
}
handle: Rectangle
{
id: handleButton
color: control.enabled ? UM.Theme.getColor("primary") : UM.Theme.getColor("quality_slider_unavailable")
implicitWidth: UM.Theme.getSize("print_setup_slider_handle").width
implicitHeight: implicitWidth
radius: Math.round(implicitWidth / 2)
opacity: 0.5
}
tickmarks: Repeater
{
id: repeater
model: control.maximumValue / control.stepSize + 1
Rectangle
{
color: control.enabled ? UM.Theme.getColor("quality_slider_available") : UM.Theme.getColor("quality_slider_unavailable")
implicitWidth: UM.Theme.getSize("print_setup_slider_tickmarks").width
implicitHeight: UM.Theme.getSize("print_setup_slider_tickmarks").height
anchors.verticalCenter: parent.verticalCenter
// Do not use Math.round otherwise the tickmarks won't be aligned
x: ((styleData.handleWidth / 2) - (implicitWidth / 2) + (index * ((repeater.width - styleData.handleWidth) / (repeater.count-1))))
radius: Math.round(implicitWidth / 2)
visible: (index % 10) == 0 // Only show steps of 10%
Label
{
text: index
visible: (index % 20) == 0 // Only show steps of 20%
anchors.horizontalCenter: parent.horizontalCenter
y: UM.Theme.getSize("thin_margin").height
renderType: Text.NativeRendering
}
}
}
}
onValueChanged: onValueChanged:
{ {
// Don't round the value if it's already the same // Don't round the value if it's already the same
if (parseInt(infillDensity.properties.value) == infillSlider.value) if (parseInt(infillDensity.properties.value) == infillSlider.value)
{ {
@ -104,228 +137,177 @@ Item
Cura.MachineManager.resetSettingForAllExtruders("infill_line_distance") Cura.MachineManager.resetSettingForAllExtruders("infill_line_distance")
} }
} }
style: SliderStyle
{
groove: Rectangle
{
id: groove
implicitWidth: 200 * screenScaleFactor
implicitHeight: 2 * screenScaleFactor
color: control.enabled ? UM.Theme.getColor("quality_slider_available") : UM.Theme.getColor("quality_slider_unavailable")
radius: 1
}
handle: Item
{
Rectangle
{
id: handleButton
anchors.centerIn: parent
color: control.enabled ? UM.Theme.getColor("quality_slider_available") : UM.Theme.getColor("quality_slider_unavailable")
implicitWidth: 10 * screenScaleFactor
implicitHeight: 10 * screenScaleFactor
radius: 10 * screenScaleFactor
}
}
tickmarks: Repeater
{
id: repeater
model: control.maximumValue / control.stepSize + 1
// check if a tick should be shown based on it's index and wether the infill density is a multiple of 10 (slider step size)
function shouldShowTick (index)
{
if (index % 10 == 0)
{
return true
}
return false
}
Rectangle
{
anchors.verticalCenter: parent.verticalCenter
color: control.enabled ? UM.Theme.getColor("quality_slider_available") : UM.Theme.getColor("quality_slider_unavailable")
width: 1 * screenScaleFactor
height: 6 * screenScaleFactor
x: Math.round(styleData.handleWidth / 2 + index * ((repeater.width - styleData.handleWidth) / (repeater.count-1)))
visible: shouldShowTick(index)
}
}
}
} }
Rectangle // Rectangle
{ // {
id: infillIcon // id: infillIcon
//
width: Math.round((parent.width / 5) - (UM.Theme.getSize("thick_margin").width)) // width: Math.round((parent.width / 5) - (UM.Theme.getSize("thick_margin").width))
height: width // height: width
//
anchors.right: parent.right // anchors.right: parent.right
anchors.top: parent.top // anchors.top: parent.top
anchors.topMargin: Math.round(UM.Theme.getSize("thick_margin").height / 2) // anchors.topMargin: Math.round(UM.Theme.getSize("thick_margin").height / 2)
//
// we loop over all density icons and only show the one that has the current density and steps // // we loop over all density icons and only show the one that has the current density and steps
Repeater // Repeater
{ // {
id: infillIconList // id: infillIconList
model: infillModel // model: infillModel
anchors.fill: parent // anchors.fill: parent
//
function activeIndex () // function activeIndex ()
{ // {
for (var i = 0; i < infillModel.count; i++) // for (var i = 0; i < infillModel.count; i++)
{ // {
var density = Math.round(infillDensity.properties.value) // var density = Math.round(infillDensity.properties.value)
var steps = Math.round(infillSteps.properties.value) // var steps = Math.round(infillSteps.properties.value)
var infillModelItem = infillModel.get(i) // var infillModelItem = infillModel.get(i)
//
if (infillModelItem != "undefined" // if (infillModelItem != "undefined"
&& density >= infillModelItem.percentageMin // && density >= infillModelItem.percentageMin
&& density <= infillModelItem.percentageMax // && density <= infillModelItem.percentageMax
&& steps >= infillModelItem.stepsMin // && steps >= infillModelItem.stepsMin
&& steps <= infillModelItem.stepsMax) // && steps <= infillModelItem.stepsMax)
{ // {
return i // return i
} // }
} // }
return -1 // return -1
} // }
//
Rectangle // Rectangle
{ // {
anchors.fill: parent // anchors.fill: parent
visible: infillIconList.activeIndex() == index // visible: infillIconList.activeIndex() == index
//
border.width: UM.Theme.getSize("default_lining").width // border.width: UM.Theme.getSize("default_lining").width
border.color: UM.Theme.getColor("quality_slider_unavailable") // border.color: UM.Theme.getColor("quality_slider_unavailable")
//
UM.RecolorImage // UM.RecolorImage
{ // {
anchors.fill: parent // anchors.fill: parent
anchors.margins: 2 * screenScaleFactor // anchors.margins: 2 * screenScaleFactor
sourceSize.width: width // sourceSize.width: width
sourceSize.height: width // sourceSize.height: width
source: UM.Theme.getIcon(model.icon) // source: UM.Theme.getIcon(model.icon)
color: UM.Theme.getColor("quality_slider_unavailable") // color: UM.Theme.getColor("quality_slider_unavailable")
} // }
} // }
} // }
} // }
//
// Gradual Support Infill Checkbox // // Gradual Support Infill Checkbox
CheckBox // CheckBox
{ // {
id: enableGradualInfillCheckBox // id: enableGradualInfillCheckBox
property alias _hovered: enableGradualInfillMouseArea.containsMouse // property alias _hovered: enableGradualInfillMouseArea.containsMouse
//
anchors.top: infillSlider.bottom // anchors.top: infillSlider.bottom
anchors.topMargin: Math.round(UM.Theme.getSize("thick_margin").height / 2) // closer to slider since it belongs to the same category // anchors.topMargin: Math.round(UM.Theme.getSize("thick_margin").height / 2) // closer to slider since it belongs to the same category
anchors.left: infillCellRight.left // anchors.left: infillSliderContainer.left
//
style: UM.Theme.styles.checkbox // style: UM.Theme.styles.checkbox
enabled: base.settingsEnabled // enabled: base.settingsEnabled
visible: infillSteps.properties.enabled == "True" // visible: infillSteps.properties.enabled == "True"
checked: parseInt(infillSteps.properties.value) > 0 // checked: parseInt(infillSteps.properties.value) > 0
//
MouseArea // MouseArea
{ // {
id: enableGradualInfillMouseArea // id: enableGradualInfillMouseArea
//
anchors.fill: parent // anchors.fill: parent
hoverEnabled: true // hoverEnabled: true
enabled: true // enabled: true
//
property var previousInfillDensity: parseInt(infillDensity.properties.value) // property var previousInfillDensity: parseInt(infillDensity.properties.value)
//
onClicked: // onClicked:
{ // {
// Set to 90% only when enabling gradual infill // // Set to 90% only when enabling gradual infill
var newInfillDensity; // var newInfillDensity;
if (parseInt(infillSteps.properties.value) == 0) // if (parseInt(infillSteps.properties.value) == 0)
{ // {
previousInfillDensity = parseInt(infillDensity.properties.value) // previousInfillDensity = parseInt(infillDensity.properties.value)
newInfillDensity = 90 // newInfillDensity = 90
} else { // } else {
newInfillDensity = previousInfillDensity // newInfillDensity = previousInfillDensity
} // }
Cura.MachineManager.setSettingForAllExtruders("infill_sparse_density", "value", String(newInfillDensity)) // Cura.MachineManager.setSettingForAllExtruders("infill_sparse_density", "value", String(newInfillDensity))
//
var infill_steps_value = 0 // var infill_steps_value = 0
if (parseInt(infillSteps.properties.value) == 0) // if (parseInt(infillSteps.properties.value) == 0)
{ // {
infill_steps_value = 5 // infill_steps_value = 5
} // }
//
Cura.MachineManager.setSettingForAllExtruders("gradual_infill_steps", "value", infill_steps_value) // Cura.MachineManager.setSettingForAllExtruders("gradual_infill_steps", "value", infill_steps_value)
} // }
//
onEntered: base.showTooltip(enableGradualInfillCheckBox, Qt.point(-infillCellRight.x, 0), // onEntered: base.showTooltip(enableGradualInfillCheckBox, Qt.point(-infillSliderContainer.x, 0),
catalog.i18nc("@label", "Gradual infill will gradually increase the amount of infill towards the top.")) // catalog.i18nc("@label", "Gradual infill will gradually increase the amount of infill towards the top."))
//
onExited: base.hideTooltip() // onExited: base.hideTooltip()
//
} // }
//
Label // Label
{ // {
id: gradualInfillLabel // id: gradualInfillLabel
height: parent.height // height: parent.height
anchors.left: enableGradualInfillCheckBox.right // anchors.left: enableGradualInfillCheckBox.right
anchors.leftMargin: Math.round(UM.Theme.getSize("thick_margin").width / 2) // anchors.leftMargin: Math.round(UM.Theme.getSize("thick_margin").width / 2)
verticalAlignment: Text.AlignVCenter; // verticalAlignment: Text.AlignVCenter;
text: catalog.i18nc("@label", "Enable gradual") // text: catalog.i18nc("@label", "Enable gradual")
font: UM.Theme.getFont("default") // font: UM.Theme.getFont("default")
color: UM.Theme.getColor("text") // color: UM.Theme.getColor("text")
} // }
} // }
//
// Infill list model for mapping icon // // Infill list model for mapping icon
ListModel // ListModel
{ // {
id: infillModel // id: infillModel
Component.onCompleted: // Component.onCompleted:
{ // {
infillModel.append({ // infillModel.append({
percentageMin: -1, // percentageMin: -1,
percentageMax: 0, // percentageMax: 0,
stepsMin: -1, // stepsMin: -1,
stepsMax: 0, // stepsMax: 0,
icon: "hollow" // icon: "hollow"
}) // })
infillModel.append({ // infillModel.append({
percentageMin: 0, // percentageMin: 0,
percentageMax: 40, // percentageMax: 40,
stepsMin: -1, // stepsMin: -1,
stepsMax: 0, // stepsMax: 0,
icon: "sparse" // icon: "sparse"
}) // })
infillModel.append({ // infillModel.append({
percentageMin: 40, // percentageMin: 40,
percentageMax: 89, // percentageMax: 89,
stepsMin: -1, // stepsMin: -1,
stepsMax: 0, // stepsMax: 0,
icon: "dense" // icon: "dense"
}) // })
infillModel.append({ // infillModel.append({
percentageMin: 90, // percentageMin: 90,
percentageMax: 9999999999, // percentageMax: 9999999999,
stepsMin: -1, // stepsMin: -1,
stepsMax: 0, // stepsMax: 0,
icon: "solid" // icon: "solid"
}) // })
infillModel.append({ // infillModel.append({
percentageMin: 0, // percentageMin: 0,
percentageMax: 9999999999, // percentageMax: 9999999999,
stepsMin: 1, // stepsMin: 1,
stepsMax: 9999999999, // stepsMax: 9999999999,
icon: "gradual" // icon: "gradual"
}) // })
} // }
} // }
} }
UM.SettingPropertyProvider UM.SettingPropertyProvider

View file

@ -12,10 +12,10 @@ Item
{ {
id: base id: base
height: childrenRect.height + 2 * padding
signal showTooltip(Item item, point location, string text) signal showTooltip(Item item, point location, string text)
signal hideTooltip() signal hideTooltip()
// width: parent.width
height: childrenRect.height + 2 * padding
property Action configureSettings property Action configureSettings
@ -28,24 +28,11 @@ Item
name: "cura" name: "cura"
} }
// Rectangle
// {
// width: parent.width - 2 * parent.padding
// anchors
// {
// left: parent.left
// right: parent.right
// top: parent.top
// margins: parent.padding
// }
// color: "blue"
// height: 50
// }
Column Column
{ {
width: parent.width - 2 * parent.padding width: parent.width - 2 * parent.padding
spacing: UM.Theme.getSize("default_margin").height spacing: UM.Theme.getSize("wide_margin").height
anchors anchors
{ {
left: parent.left left: parent.left
@ -55,33 +42,27 @@ Item
} }
// TODO // TODO
property real labelColumnWidth: Math.round(width / 3) property real firstColumnWidth: Math.round(width / 3)
property real settingsColumnWidth: width - labelColumnWidth
RecommendedQualityProfileSelector RecommendedQualityProfileSelector
{ {
width: parent.width width: parent.width
// TODO Create a reusable component with these properties to not define them separately for each component // TODO Create a reusable component with these properties to not define them separately for each component
property real labelColumnWidth: parent.labelColumnWidth labelColumnWidth: parent.firstColumnWidth
property real settingsColumnWidth: parent.settingsColumnWidth
} }
// RecommendedInfillDensitySelector RecommendedInfillDensitySelector
// { {
// width: parent.width width: parent.width
// height: childrenRect.height // TODO Create a reusable component with these properties to not define them separately for each component
// // TODO Create a reusable component with these properties to not define them separately for each component labelColumnWidth: parent.firstColumnWidth
// property real labelColumnWidth: parent.labelColumnWidth }
// property real settingsColumnWidth: parent.settingsColumnWidth
// }
// //
// RecommendedSupportSelector // RecommendedSupportSelector
// { // {
// width: parent.width // width: parent.width
// height: childrenRect.height
// // TODO Create a reusable component with these properties to not define them separately for each component // // TODO Create a reusable component with these properties to not define them separately for each component
// property real labelColumnWidth: parent.labelColumnWidth // property real firstColumnWidth: parent.labelColumnWidth
// property real settingsColumnWidth: parent.settingsColumnWidth
// } // }

View file

@ -17,6 +17,9 @@ Item
id: qualityRow id: qualityRow
height: childrenRect.height height: childrenRect.height
property real labelColumnWidth: Math.round(width / 3)
property real settingsColumnWidth: width - labelColumnWidth
Timer Timer
{ {
id: qualitySliderChangeTimer id: qualitySliderChangeTimer
@ -158,6 +161,7 @@ Item
} }
} }
// Here are the elements that are shown in the left column
Item Item
{ {
id: titleRow id: titleRow
@ -210,6 +214,7 @@ Item
{ {
anchors.left: speedSlider.left anchors.left: speedSlider.left
anchors.top: speedSlider.bottom anchors.top: speedSlider.bottom
height: childrenRect.height
Repeater Repeater
{ {
@ -219,6 +224,8 @@ Item
{ {
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
anchors.top: parent.top anchors.top: parent.top
// The height has to be set manually, otherwise it's not automatically calculated in the repeater
height: UM.Theme.getSize("default_margin").height
color: (Cura.MachineManager.activeMachine != null && Cura.QualityProfilesDropDownMenuModel.getItem(index).available) ? UM.Theme.getColor("quality_slider_available") : UM.Theme.getColor("quality_slider_unavailable") color: (Cura.MachineManager.activeMachine != null && Cura.QualityProfilesDropDownMenuModel.getItem(index).available) ? UM.Theme.getColor("quality_slider_available") : UM.Theme.getColor("quality_slider_unavailable")
text: text:
{ {
@ -268,7 +275,7 @@ Item
} }
} }
//Print speed slider // Print speed slider
// Two sliders are created, one at the bottom with the unavailable qualities // Two sliders are created, one at the bottom with the unavailable qualities
// and the other at the top with the available quality profiles and so the handle to select them. // and the other at the top with the available quality profiles and so the handle to select them.
Item Item
@ -287,6 +294,8 @@ Item
Slider Slider
{ {
id: unavailableSlider id: unavailableSlider
width: parent.width
height: qualitySlider.height // Same height as the slider that is on top height: qualitySlider.height // Same height as the slider that is on top
updateValueWhileDragging : false updateValueWhileDragging : false
tickmarksEnabled: true tickmarksEnabled: true
@ -297,8 +306,6 @@ Item
maximumValue: qualityModel.totalTicks maximumValue: qualityModel.totalTicks
stepSize: 1 stepSize: 1
width: parent.width
style: SliderStyle style: SliderStyle
{ {
//Draw Unvailable line //Draw Unvailable line
@ -329,7 +336,7 @@ Item
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
// Do not use Math.round otherwise the tickmarks won't be aligned // Do not use Math.round otherwise the tickmarks won't be aligned
x: ((UM.Theme.getSize("print_setup_slider_handle").width / 2) - (UM.Theme.getSize("print_setup_slider_tickmarks").width / 2) + (qualityModel.qualitySliderStepWidth * index)) x: ((UM.Theme.getSize("print_setup_slider_handle").width / 2) - (implicitWidth / 2) + (qualityModel.qualitySliderStepWidth * index))
radius: Math.round(implicitWidth / 2) radius: Math.round(implicitWidth / 2)
} }
} }
@ -354,11 +361,19 @@ Item
Slider Slider
{ {
id: qualitySlider id: qualitySlider
width: qualityModel.qualitySliderStepWidth * (qualityModel.availableTotalTicks - 1) + UM.Theme.getSize("print_setup_slider_handle").width
height: UM.Theme.getSize("print_setup_slider_handle").height // The handle is the widest element of the slider height: UM.Theme.getSize("print_setup_slider_handle").height // The handle is the widest element of the slider
enabled: qualityModel.totalTicks > 0 && !Cura.SimpleModeSettingsManager.isProfileCustomized enabled: qualityModel.totalTicks > 0 && !Cura.SimpleModeSettingsManager.isProfileCustomized
visible: qualityModel.availableTotalTicks > 0 visible: qualityModel.availableTotalTicks > 0
updateValueWhileDragging : false updateValueWhileDragging : false
anchors
{
right: parent.right
rightMargin: qualityModel.qualitySliderMarginRight
}
minimumValue: qualityModel.qualitySliderAvailableMin >= 0 ? qualityModel.qualitySliderAvailableMin : 0 minimumValue: qualityModel.qualitySliderAvailableMin >= 0 ? qualityModel.qualitySliderAvailableMin : 0
// maximumValue must be greater than minimumValue to be able to see the handle. While the value is strictly // maximumValue must be greater than minimumValue to be able to see the handle. While the value is strictly
// speaking not always correct, it seems to have the correct behavior (switching from 0 available to 1 available) // speaking not always correct, it seems to have the correct behavior (switching from 0 available to 1 available)
@ -367,11 +382,6 @@ Item
value: qualityModel.qualitySliderActiveIndex value: qualityModel.qualitySliderActiveIndex
width: qualityModel.qualitySliderStepWidth * (qualityModel.availableTotalTicks - 1) + UM.Theme.getSize("print_setup_slider_handle").width
anchors.right: parent.right
anchors.rightMargin: qualityModel.qualitySliderMarginRight
style: SliderStyle style: SliderStyle
{ {
// Draw Available line // Draw Available line