Merge pull request #1495 from fieldOfView/feature_draggable_range_slider2

Use a single draggable range slider in Layerview
This commit is contained in:
jack 2017-03-07 11:43:17 +01:00 committed by GitHub
commit 3b1a15e1c4
3 changed files with 241 additions and 63 deletions

View file

@ -163,6 +163,8 @@ class LayerView(View):
self._current_layer_num = 0 self._current_layer_num = 0
if self._current_layer_num > self._max_layers: if self._current_layer_num > self._max_layers:
self._current_layer_num = self._max_layers self._current_layer_num = self._max_layers
if self._current_layer_num < self._minimum_layer_num:
self._minimum_layer_num = self._current_layer_num
self._startUpdateTopLayers() self._startUpdateTopLayers()
@ -173,6 +175,10 @@ class LayerView(View):
self._minimum_layer_num = value self._minimum_layer_num = value
if self._minimum_layer_num < 0: if self._minimum_layer_num < 0:
self._minimum_layer_num = 0 self._minimum_layer_num = 0
if self._minimum_layer_num > self._max_layers:
self._minimum_layer_num = self._max_layers
if self._minimum_layer_num > self._current_layer_num:
self._current_layer_num = self._minimum_layer_num
self._startUpdateTopLayers() self._startUpdateTopLayers()
@ -279,13 +285,15 @@ class LayerView(View):
def event(self, event): def event(self, event):
modifiers = QApplication.keyboardModifiers() modifiers = QApplication.keyboardModifiers()
ctrl_is_active = modifiers == Qt.ControlModifier ctrl_is_active = modifiers & Qt.ControlModifier
shift_is_active = modifiers & Qt.ShiftModifier
if event.type == Event.KeyPressEvent and ctrl_is_active: if event.type == Event.KeyPressEvent and ctrl_is_active:
amount = 10 if shift_is_active else 1
if event.key == KeyEvent.UpKey: if event.key == KeyEvent.UpKey:
self.setLayer(self._current_layer_num + 1) self.setLayer(self._current_layer_num + amount)
return True return True
if event.key == KeyEvent.DownKey: if event.key == KeyEvent.DownKey:
self.setLayer(self._current_layer_num - 1) self.setLayer(self._current_layer_num - amount)
return True return True
if event.type == Event.ViewActivateEvent: if event.type == Event.ViewActivateEvent:

View file

@ -10,7 +10,6 @@ import UM 1.0 as UM
Item Item
{ {
id: base
width: { width: {
if (UM.LayerView.compatibilityMode) { if (UM.LayerView.compatibilityMode) {
return UM.Theme.getSize("layerview_menu_size_compatibility").width; return UM.Theme.getSize("layerview_menu_size_compatibility").width;
@ -324,86 +323,254 @@ Item
} }
Slider Item
{
id: sliderMinimumLayer
anchors {
top: parent.top
bottom: parent.bottom
right: layerViewMenu.right
margins: UM.Theme.getSize("slider_layerview_margin").height
rightMargin: UM.Theme.getSize("slider_layerview_margin").width * 0.8
}
width: UM.Theme.getSize("slider_layerview_size").width
orientation: Qt.Vertical
minimumValue: 0;
maximumValue: UM.LayerView.numLayers - 1;
stepSize: 1
property real pixelsPerStep: ((height - UM.Theme.getSize("slider_handle").height) / (maximumValue - minimumValue)) * stepSize
value: UM.LayerView.minimumLayer
onValueChanged: {
UM.LayerView.setMinimumLayer(value)
if (value > UM.LayerView.currentLayer) {
UM.LayerView.setCurrentLayer(value);
}
}
style: UM.Theme.styles.slider;
}
Slider
{ {
id: slider id: slider
width: handleSize
height: parent.height - 2*UM.Theme.getSize("slider_layerview_margin").height
anchors.top: parent.top
anchors.topMargin: UM.Theme.getSize("slider_layerview_margin").height
anchors.right: layerViewMenu.right
anchors.rightMargin: UM.Theme.getSize("slider_layerview_margin").width
anchors { property real handleSize: UM.Theme.getSize("slider_handle").width
top: parent.top property real handleRadius: handleSize / 2
bottom: parent.bottom property real minimumRangeHandleSize: UM.Theme.getSize("slider_handle").width / 2
right: layerViewMenu.right property real trackThickness: UM.Theme.getSize("slider_groove").width
margins: UM.Theme.getSize("slider_layerview_margin").height property real trackRadius: trackThickness / 2
rightMargin: UM.Theme.getSize("slider_layerview_margin").width * 0.2 property real trackBorderWidth: UM.Theme.getSize("default_lining").width
property color upperHandleColor: UM.Theme.getColor("slider_handle")
property color lowerHandleColor: UM.Theme.getColor("slider_handle")
property color rangeHandleColor: UM.Theme.getColor("slider_groove_fill")
property color trackColor: UM.Theme.getColor("slider_groove")
property color trackBorderColor: UM.Theme.getColor("slider_groove_border")
property real maximumValue: UM.LayerView.numLayers
property real minimumValue: 0
property real minimumRange: 0
property bool roundValues: true
property var activeHandle: upperHandle
property bool layersVisible: UM.LayerView.layerActivity && Printer.platformActivity ? true : false
function getUpperValueFromHandle()
{
var result = upperHandle.y / (height - (2 * handleSize + minimumRangeHandleSize));
result = maximumValue + result * (minimumValue - (maximumValue - minimumRange));
result = roundValues ? Math.round(result) | 0 : result;
return result;
} }
width: UM.Theme.getSize("slider_layerview_size").width
orientation: Qt.Vertical function getLowerValueFromHandle()
minimumValue: 0; {
maximumValue: UM.LayerView.numLayers; var result = (lowerHandle.y - (handleSize + minimumRangeHandleSize)) / (height - (2 * handleSize + minimumRangeHandleSize));
stepSize: 1 result = maximumValue - minimumRange + result * (minimumValue - (maximumValue - minimumRange));
result = roundValues ? Math.round(result) : result;
return result;
}
property real pixelsPerStep: ((height - UM.Theme.getSize("slider_handle").height) / (maximumValue - minimumValue)) * stepSize; function setUpperValue(value)
{
var value = (value - maximumValue) / (minimumValue - maximumValue);
var new_upper_y = Math.round(value * (height - (2 * handleSize + minimumRangeHandleSize)));
value: UM.LayerView.currentLayer if(new_upper_y != upperHandle.y)
onValueChanged: { {
upperHandle.y = new_upper_y;
}
rangeHandle.height = lowerHandle.y - (upperHandle.y + upperHandle.height);
}
function setLowerValue(value)
{
var value = (value - maximumValue) / (minimumValue - maximumValue);
var new_lower_y = Math.round((handleSize + minimumRangeHandleSize) + value * (height - (2 * handleSize + minimumRangeHandleSize)));
if(new_lower_y != lowerHandle.y)
{
lowerHandle.y = new_lower_y;
}
rangeHandle.height = lowerHandle.y - (upperHandle.y + upperHandle.height);
}
Connections
{
target: UM.LayerView
onMinimumLayerChanged: slider.setLowerValue(UM.LayerView.minimumLayer)
onCurrentLayerChanged: slider.setUpperValue(UM.LayerView.currentLayer)
}
Rectangle {
width: parent.trackThickness
height: parent.height - parent.handleSize
radius: parent.trackRadius
anchors.centerIn: parent
color: parent.trackColor
border.width: parent.trackBorderWidth;
border.color: parent.trackBorderColor;
}
Item {
id: rangeHandle
y: upperHandle.y + upperHandle.height
width: parent.handleSize
height: parent.minimumRangeHandleSize
anchors.horizontalCenter: parent.horizontalCenter
visible: slider.layersVisible
property real value: UM.LayerView.currentLayer
function setValue(value)
{
var range = upperHandle.value - lowerHandle.value;
value = Math.min(value, slider.maximumValue);
value = Math.max(value, slider.minimumValue + range);
UM.LayerView.setCurrentLayer(value); UM.LayerView.setCurrentLayer(value);
if (value < UM.LayerView.minimumLayer) { UM.LayerView.setMinimumLayer(value - range);
}
Rectangle {
anchors.centerIn: parent
width: parent.parent.trackThickness - 2 * parent.parent.trackBorderWidth
height: parent.height + parent.parent.handleSize
color: parent.parent.rangeHandleColor
}
MouseArea {
anchors.fill: parent
drag.target: parent
drag.axis: Drag.YAxis
drag.minimumY: upperHandle.height
drag.maximumY: parent.parent.height - (parent.height + lowerHandle.height)
onPressed: parent.parent.activeHandle = rangeHandle
onPositionChanged:
{
upperHandle.y = parent.y - upperHandle.height
lowerHandle.y = parent.y + parent.height
var upper_value = slider.getUpperValueFromHandle();
var lower_value = upper_value - (upperHandle.value - lowerHandle.value);
UM.LayerView.setCurrentLayer(upper_value);
UM.LayerView.setMinimumLayer(lower_value);
}
}
}
Rectangle {
id: upperHandle
y: parent.height - (parent.minimumRangeHandleSize + 2 * parent.handleSize)
width: parent.handleSize
height: parent.handleSize
anchors.horizontalCenter: parent.horizontalCenter
radius: parent.handleRadius
color: parent.upperHandleColor
visible: slider.layersVisible
property real value: UM.LayerView.currentLayer
function setValue(value)
{
UM.LayerView.setCurrentLayer(value);
}
MouseArea {
anchors.fill: parent
drag.target: parent
drag.axis: Drag.YAxis
drag.minimumY: 0
drag.maximumY: parent.parent.height - (2 * parent.parent.handleSize + parent.parent.minimumRangeHandleSize)
onPressed: parent.parent.activeHandle = upperHandle
onPositionChanged:
{
if(lowerHandle.y - (upperHandle.y + upperHandle.height) < parent.parent.minimumRangeHandleSize)
{
lowerHandle.y = upperHandle.y + upperHandle.height + parent.parent.minimumRangeHandleSize;
}
rangeHandle.height = lowerHandle.y - (upperHandle.y + upperHandle.height);
UM.LayerView.setCurrentLayer(slider.getUpperValueFromHandle());
}
}
}
Rectangle {
id: lowerHandle
y: parent.height - parent.handleSize
width: parent.handleSize
height: parent.handleSize
anchors.horizontalCenter: parent.horizontalCenter
radius: parent.handleRadius
color: parent.lowerHandleColor
visible: slider.layersVisible
property real value: UM.LayerView.minimumLayer
function setValue(value)
{
UM.LayerView.setMinimumLayer(value); UM.LayerView.setMinimumLayer(value);
} }
MouseArea {
anchors.fill: parent
drag.target: parent
drag.axis: Drag.YAxis
drag.minimumY: upperHandle.height + parent.parent.minimumRangeHandleSize
drag.maximumY: parent.parent.height - parent.height
onPressed: parent.parent.activeHandle = lowerHandle
onPositionChanged:
{
if(lowerHandle.y - (upperHandle.y + upperHandle.height) < parent.parent.minimumRangeHandleSize)
{
upperHandle.y = lowerHandle.y - (upperHandle.height + parent.parent.minimumRangeHandleSize);
}
rangeHandle.height = lowerHandle.y - (upperHandle.y + upperHandle.height)
UM.LayerView.setMinimumLayer(slider.getLowerValueFromHandle());
}
}
} }
style: UM.Theme.styles.slider; UM.PointingRectangle
Rectangle
{ {
x: parent.width + UM.Theme.getSize("slider_layerview_background").width / 2; x: parent.width + UM.Theme.getSize("slider_layerview_background").width / 2;
y: parent.height - (parent.value * parent.pixelsPerStep) - UM.Theme.getSize("slider_handle").height * 1.25; y: Math.floor(slider.activeHandle.y + slider.activeHandle.height / 2 - height / 2);
height: UM.Theme.getSize("slider_handle").height + UM.Theme.getSize("default_margin").height target: Qt.point(0, slider.activeHandle.y + slider.activeHandle.height / 2)
arrowSize: UM.Theme.getSize("default_arrow").width
height: (Math.floor(UM.Theme.getSize("slider_handle").height + UM.Theme.getSize("default_margin").height) / 2) * 2 // Make sure height has an integer middle so drawing a pointy border is easier
width: valueLabel.width + UM.Theme.getSize("default_margin").width width: valueLabel.width + UM.Theme.getSize("default_margin").width
Behavior on height { NumberAnimation { duration: 50; } } Behavior on height { NumberAnimation { duration: 50; } }
border.width: UM.Theme.getSize("default_lining").width color: UM.Theme.getColor("lining");
border.color: UM.Theme.getColor("slider_groove_border")
color: UM.Theme.getColor("tool_panel_background")
visible: UM.LayerView.layerActivity && Printer.platformActivity ? true : false visible: slider.layersVisible
UM.PointingRectangle
{
color: UM.Theme.getColor("tool_panel_background")
target: Qt.point(0, height / 2 + UM.Theme.getSize("default_lining").width)
arrowSize: UM.Theme.getSize("default_arrow").width
anchors.fill: parent
anchors.margins: UM.Theme.getSize("default_lining").width
MouseArea //Catch all mouse events (so scene doesnt handle them)
{
anchors.fill: parent
}
}
TextField TextField
{ {
id: valueLabel id: valueLabel
property string maxValue: slider.maximumValue + 1 property string maxValue: slider.maximumValue + 1
text: slider.value + 1 text: slider.activeHandle.value + 1
horizontalAlignment: TextInput.AlignRight; horizontalAlignment: TextInput.AlignRight;
onEditingFinished: onEditingFinished:
{ {
@ -413,7 +580,7 @@ Item
cursorPosition = 0; cursorPosition = 0;
if(valueLabel.text != '') if(valueLabel.text != '')
{ {
slider.value = valueLabel.text - 1; slider.activeHandle.setValue(valueLabel.text - 1);
} }
} }
validator: IntValidator { bottom: 1; top: slider.maximumValue + 1; } validator: IntValidator { bottom: 1; top: slider.maximumValue + 1; }
@ -429,6 +596,9 @@ Item
font: UM.Theme.getFont("default"); font: UM.Theme.getFont("default");
background: Item { } background: Item { }
} }
Keys.onUpPressed: slider.activeHandle.setValue(slider.activeHandle.value + ((event.modifiers & Qt.ShiftModifier) ? 10 : 1))
Keys.onDownPressed: slider.activeHandle.setValue(slider.activeHandle.value - ((event.modifiers & Qt.ShiftModifier) ? 10 : 1))
} }
BusyIndicator BusyIndicator

View file

@ -292,7 +292,7 @@
"slider_handle": [1.5, 1.5], "slider_handle": [1.5, 1.5],
"slider_layerview_size": [1.0, 22.0], "slider_layerview_size": [1.0, 22.0],
"slider_layerview_background": [4.0, 0.0], "slider_layerview_background": [4.0, 0.0],
"slider_layerview_margin": [3.0, 1.0], "slider_layerview_margin": [1.0, 1.0],
"layerview_menu_size": [16.5, 21.0], "layerview_menu_size": [16.5, 21.0],
"layerview_menu_size_compatibility": [22, 23.0], "layerview_menu_size_compatibility": [22, 23.0],