Index: sources/gui/qml/components/RangeRect.qml =================================================================== diff -u -r9419d09af625fa3b1291da079df2df0589358ff6 -r2f0b2e204b42597e08be24df48a3b3d470b73051 --- sources/gui/qml/components/RangeRect.qml (.../RangeRect.qml) (revision 9419d09af625fa3b1291da079df2df0589358ff6) +++ sources/gui/qml/components/RangeRect.qml (.../RangeRect.qml) (revision 2f0b2e204b42597e08be24df48a3b3d470b73051) @@ -43,6 +43,8 @@ property real touchMargin : 0 property real leftRightTouchMargin: 0 + property bool isRoundedEnds : true + property bool hasBorder : true function adjustOverlap() { // Due to font size not being fixed and be different depending on text, @@ -65,8 +67,11 @@ height : parent.height color : Colors.backgroundRangeRect - radius : Variables.rangeRectRadius + radius : isRoundedEnds ? (height/2) : Variables.rangeRectRadius + border.width: hasBorder ? Variables.rangeRectBorderWidth : 0 + border.color: Colors.rangeRectBorderColor + Text { id: _textMinimum visible : false font.pixelSize : Fonts.fontPixelRangeRectText Index: sources/gui/qml/components/RangeSlider.qml =================================================================== diff -u -r2b16e255a35e0f716bfa9d6943b35e4199dcf3b0 -r2f0b2e204b42597e08be24df48a3b3d470b73051 --- sources/gui/qml/components/RangeSlider.qml (.../RangeSlider.qml) (revision 2b16e255a35e0f716bfa9d6943b35e4199dcf3b0) +++ sources/gui/qml/components/RangeSlider.qml (.../RangeSlider.qml) (revision 2f0b2e204b42597e08be24df48a3b3d470b73051) @@ -67,6 +67,9 @@ property bool maxAdjusted : false ///< first time user adjustment happens property bool hasAdjust : false ///< if set to true then component is grayed out until both min and max are adjusted + property bool showTickmarks : true ///< Indicate whether tickMarks should be shown + property bool isTickMarksRound : true ///< Indicate whether the tickmakrs are round + onHasAdjustChanged : { setAdjusted() } @@ -79,11 +82,15 @@ /// root attributes clip : false + color: Colors.transparent height : Variables.progressbarHeight touchMargin : 25 leftRightTouchMargin: _root.diameter / 2 + isRoundedEnds : true + hasBorder : true + minimum : 0 maximum : 0 @@ -108,7 +115,7 @@ /// function setAdjusted() { function check() { - _rangeRect .color = minAdjusted && maxAdjusted ? Colors.createTreatmentActive : Colors.createTreatmentInactive + _rangeRect .color = minAdjusted && maxAdjusted ? Colors.sliderHighlightColor : Colors.createTreatmentInactive _handlerLeft .color = minAdjusted ? Colors.createTreatmentActive: Colors.createTreatmentInactive _handlerRight.color = maxAdjusted ? Colors.createTreatmentActive: Colors.createTreatmentInactive } @@ -245,8 +252,9 @@ width : minmaxDiff ? ((parent.width * (upperBound - lowerBound )) / minmaxDiff) : minmaxDiff height : parent.height - radius : 0 decimal : _root.decimal + isRoundedEnds : _root.isRoundedEnds + hasBorder : _root.hasBorder minText { visible: false @@ -278,13 +286,20 @@ Loader { id: _ticksLoader active : _root.ticks anchors.fill : parent - sourceComponent : TickMarks { + sourceComponent : _root.showTickmarks ? _tickMarkFactory : undefined + } + + Component { id:_tickMarkFactory + TickMarks { decimal : _root.decimal minimum : _root.minimum maximum : _root.maximum step : _root.step stepSnap : _root.stepSnap textColor : _root.color + lineTickMarkHeight: _rangeRect.height + isTickMarkRound : _root.isTickMarksRound + yDisplacement : _root.isTickMarksRound ? (-_rangeRect.height) : 0 } } Index: sources/gui/qml/components/Slider.qml =================================================================== diff -u -r5f6975c6ee7823fc884328418298128cdb97107f -r2f0b2e204b42597e08be24df48a3b3d470b73051 --- sources/gui/qml/components/Slider.qml (.../Slider.qml) (revision 5f6975c6ee7823fc884328418298128cdb97107f) +++ sources/gui/qml/components/Slider.qml (.../Slider.qml) (revision 2f0b2e204b42597e08be24df48a3b3d470b73051) @@ -25,9 +25,11 @@ */ RangeRect { id: _root property alias value : _progressRect.value + property real displayedValue : 0 property real step : 1 property bool stepSnap : false + property bool stepSnapOnRelease : true property bool ticks : false @@ -48,10 +50,46 @@ property int tickMarksThickness : 2 - signal progressRectClicked() - signal progressRectDragged() signal activeChanged() + signal handleSelected() + function incrementValue (vInStepSegments) { + // in case the slider is not yet activated, activate + if (!isActive) { + setActive(true) + } + updateValue(vInStepSegments, true) + } + + function decrementValue (vInStepSegments) { + // in case the slider is not yet activated, activate + if (!isActive) { + setActive(true) + } + updateValue(vInStepSegments, false) + } + + function updateValue(vInStepSegments, vIsIncrement) { + let amountChanged = 1 + if (vInStepSegments) { + amountChanged = step + } + + let newValue = Number.NaN + if(vIsIncrement) { + newValue = _root.value + amountChanged + } else { + newValue = _root.value - amountChanged + } + + // Capping values based on min/max threshold + if ( newValue < minimum ) newValue = minimum + if ( newValue > maximum ) newValue = maximum + + // update new value + update(newValue.toFixed(decimal)) + } + function setActive(active) { if (active) { color = Colors.sliderHighlightColor @@ -60,11 +98,6 @@ color = Colors.createTreatmentInactive handlerColor = Colors.createTreatmentInactive } - - if (active !== isActive) { - isActive = active; - activeChanged() - } } onIsActiveChanged: { @@ -75,9 +108,17 @@ activeChanged() } - height : Variables.progressbarHeight - touchMargin : 25 + onValueChanged: { + if ( _root.isActive ) { + // update the displayed value to the attentive snapped value + _root.displayedValue = calculateRoundedValue(_root.value) + } + } + height : Variables.progressbarHeight + touchMargin : 25 + leftRightTouchMargin: _handler.width/2 + minimum : 0 maximum : 0 @@ -104,6 +145,10 @@ font.bold : false } + function calculateRoundedValue(vValue){ + return (Math.round(vValue / step) * step).toFixed(decimal) + } + function getValueOfX(x) { return ( x * ( maximum - minimum ) ) / width + minimum } @@ -112,42 +157,51 @@ _root.value = vValue } - function setValue(x) { - let mValue = 0 + function calculateValue(x, isSnappingToTicks) { let mMinimum = Number(_root.minimum.toFixed(decimal)) let mMaximum = Number(_root.maximum.toFixed(decimal)) - if ( x < 0 ) { mValue = mMinimum; update(mValue); return; } - if ( x > width ) { mValue = mMaximum; update(mValue); return; } - mValue = getValueOfX(x) + if(x < _handler.width) { + // The outside of the slider, lower bound case + return mMinimum + } - if ( step === 1 ) { mValue = parseInt(mValue); update(mValue); return; } + if(x > _root.width ) { + // The outside of the slider, upper bound case + return mMaximum + } + // Calculate the in-between : + let mValue = 0 let start = 0 + if ( ! stepSnap ) start = mMinimum - mValue = Math.round((mValue - start) / step) * step + start - let decimals = Math.round(-Math.log10(step)) - if (decimals > 0) { - mValue = mValue.toFixed(decimals) + mValue = getValueOfX(x) + + // special handling for the case that the step segments are less than the handle's width + let stepWidth = width / ((mMaximum - mMinimum) / step) + if ( stepWidth < _handler.width ) { + let valueStepCount = parseInt(mValue / step) + mValue = valueStepCount * step + return mValue.toFixed(decimal) } - if ( mValue < mMinimum ) { mValue = mMinimum; update(mValue); return; } - if ( mValue > mMaximum ) { mValue = mMaximum; update(mValue); return; } + if ( isSnappingToTicks ) { + mValue = Math.round((mValue - start) / step) * step + start + let additionalDecimalResolution = 3 + mValue = mValue.toFixed(decimal + additionalDecimalResolution) - update(mValue); return; - } + } - function setHandlerPosition() { - if ( _progressRect.width <= 0 ) { - _handler.x = 0 - _root.tickMarksThickness - } else - if ( _progressRect.width >= _root.width - _root.tickMarksThickness ) { - _handler.x = _root.width - _handler.width + _root.tickMarksThickness + // For sliders with decimal min, max, values, we need to add refinement to + // the value to achieve slider handle movement close to those of the whole number sliders + if ( decimal > 0 ) { } - else { - _handler.x = _progressRect.width - _handler.width / 2 - } + + if ( mValue < mMinimum ) { return mMinimum; } + if ( mValue > mMaximum ) { return mMaximum; } + return mValue; } // used loader for performance since it may not always be required. @@ -169,6 +223,7 @@ } } ProgressRect { id: _progressRect + property real previousSliderValue: Number.NaN color : Colors.transparent decimal : _root.decimal minimum : _root.minimum @@ -189,21 +244,44 @@ } } + function updateHandleValue(vCurrentPositionX) + { + // Passing false for snapping to get exact value in respect to x + let newCurrentValue = calculateValue(vCurrentPositionX, false) + + // Check the cursor's current value to determine if the cursor had moved + // Do not avoid type coercion, it will produce undesired results + if(newCurrentValue != _progressRect.previousSliderValue) { + // The cursor did move + if(stepSnapOnRelease) { + // check for snapping state to save an iteration of recalculation if snap is off + newCurrentValue = calculateValue(vCurrentPositionX, stepSnapOnRelease) + } + + // Update the slider's value since the cursor did move + update(newCurrentValue) + _progressRect.previousSliderValue = newCurrentValue + } + } + onDragged: { - setValue(vMouseEvent.x) + // On position change / dragging, the value is updated based on value calculated + // Need to account for the extended touch areas + let adjustedXPosition = vMouseEvent.x - _progressRect.leftRightTouchMargin + let newCurrentValue = calculateValue(adjustedXPosition, !stepSnapOnRelease) + update(newCurrentValue) } - onClicked: { - setValue(vMouseEvent.x) - } - onPressed: { - setValue(vMouseEvent.x) - } + onReleased: { - setValue(vMouseEvent.x) + if (isActive) { + // Need to account for the extended touch areas + updateHandleValue(vMouseEvent.x - _progressRect.leftRightTouchMargin) + } } Rectangle { id: _handler - property real diameter : Variables.progressbarHandler + property bool handleSelected : false + property real diameter : Variables.progressbarHandler anchors.verticalCenter : parent.verticalCenter anchors.horizontalCenter: _progressRect.right @@ -216,5 +294,18 @@ width: Variables.progressbarHandlerBorderWidth color: Colors.textMain } + MouseArea { + anchors.fill: parent + propagateComposedEvents: true + onPressed: { + // Handle was inactive and was selected, update the value + if ( !_root.isActive ) { + value = inActiveZero ? 0 : minimum + _root.displayedValue = calculateRoundedValue(value) + } + mouse.accepted = false // allow propagtion to the lower mouse areas + handleSelected() // emit + } + } } } Index: sources/gui/qml/components/SliderCreateTreatment.qml =================================================================== diff -u -r839893734937449efb6e7c31787d2c44515b69af -r2f0b2e204b42597e08be24df48a3b3d470b73051 --- sources/gui/qml/components/SliderCreateTreatment.qml (.../SliderCreateTreatment.qml) (revision 839893734937449efb6e7c31787d2c44515b69af) +++ sources/gui/qml/components/SliderCreateTreatment.qml (.../SliderCreateTreatment.qml) (revision 2f0b2e204b42597e08be24df48a3b3d470b73051) @@ -42,12 +42,15 @@ property bool active : false property bool valid : true + property alias showAdjustButtons : _sliderArrows.visible + property bool isUsingDisplayValue : true // indicate whether using the slider's actual value or displayedValue + signal pressed () signal released() height : Variables.createTreatmentSliderHeight width : Variables.createTreatmentSliderWidth - color : "transparent" + color : Colors.transparent anchors.horizontalCenter: parent.horizontalCenter @@ -71,7 +74,7 @@ if ( _slider.value === 0 && zeroLabel !== "" ) { return _root.zeroLabel } - mValue = _slider.value + mValue = isUsingDisplayValue ? _slider.displayedValue : _slider.value } return mValue + unit } @@ -118,11 +121,25 @@ ticks : true isRoundedEnds : true hasBorder : true - onPressed : { setInteractive(false) ; _root.pressed ( ) ; setActiveValid( ) } - onDragged : { setInteractive(false) ; ; setActiveValid( ) } - onReleased : { setInteractive(true ) ; _root.released( ) ; } - onClicked : { ; ; setActiveValid( ) } - onProgressRectClicked : { ; ; setActiveValid( ) } - onProgressRectDragged : { ; ; setActiveValid( ) } + onDragged : { setInteractive(false) ; ; setActiveValid( );} + onPressed : { setInteractive(false) ; _root.pressed ( ) ; } + onReleased : { setInteractive(true ) ; _root.released( ) ; } + onHandleSelected : { setActiveValid(); } } + + SliderArrows{ id:_sliderArrows + visible : true + anchors.verticalCenter : _slider.verticalCenter + anchors.left : _slider.right + anchors.leftMargin : Variables.sliderAdjustButtonLeftMargin + + onIncrementValue : { + setActiveValid() + _slider.incrementValue(true) + } + onDecrementValue : { + setActiveValid() + _slider.decrementValue(true) + } + } } Index: sources/gui/qml/globals/Variables.qml =================================================================== diff -u -rf813d68fd04134b788273466fbf754b8996b4ac2 -r2f0b2e204b42597e08be24df48a3b3d470b73051 --- sources/gui/qml/globals/Variables.qml (.../Variables.qml) (revision f813d68fd04134b788273466fbf754b8996b4ac2) +++ sources/gui/qml/globals/Variables.qml (.../Variables.qml) (revision 2f0b2e204b42597e08be24df48a3b3d470b73051) @@ -66,9 +66,13 @@ readonly property int dialogHeight : applicationHeight - dialogMargin readonly property int dialogRadius : 5 + readonly property real sliderDefaultRoundTickMarkDiameter : 5 + readonly property real sliderCreateTreatmentHeight : 15 + readonly property int rangeRectMargin : 1 readonly property int rangeRectRadius : 2 readonly property int rangeRectTextMargin : 7 + readonly property int rangeRectBorderWidth : 2 readonly property int rangeMarkerHeight : 60 readonly property int rangeMarkerHeightMidle : 40 readonly property int rangeMarkerHeightShort : 20 @@ -98,7 +102,6 @@ readonly property int checkListViewItemWidth : 350 readonly property int checkListViewItemHeight : 60 - readonly property int pauseIconDiameter : 60 readonly property int topBarMenuHeight : 100 readonly property int sliderCircleDiameter : 30 @@ -117,7 +120,7 @@ readonly property int createTreatmentSubTableHeight : 50 readonly property int createTreatmentSubTableWidth : 500 readonly property int createTreatmentSliderMargin : 40 - readonly property int createTreatmentSliderHeight : 50 + readonly property int createTreatmentSliderHeight : 65 readonly property int createTreatmentSliderWidth : 750 readonly property int ultrafiltrationProgressbarWidth : 880 @@ -198,6 +201,9 @@ // Saline readonly property int salinePrecision : 1 + // Dialysate Temperature + readonly property int dialysateTempPrecision : 1 + function sizeConverted(vSize, vSizePowers, vRound = 2) { return ( vSize / vSizePowers // convert from byte to Giga byte Index: sources/gui/qml/pages/MainStack.qml =================================================================== diff -u -ra6586ea871f21a08e7d50552983360fb5e344b3a -r2f0b2e204b42597e08be24df48a3b3d470b73051 --- sources/gui/qml/pages/MainStack.qml (.../MainStack.qml) (revision a6586ea871f21a08e7d50552983360fb5e344b3a) +++ sources/gui/qml/pages/MainStack.qml (.../MainStack.qml) (revision 2f0b2e204b42597e08be24df48a3b3d470b73051) @@ -82,6 +82,8 @@ value : vHDPOSTData.itemIndex width : _dialityLogo.width + 50 height : 3 + progress.border.width: 0 + border.width: 0 minText .visible: false maxText .visible: false marker .visible: false Index: sources/gui/qml/pages/pretreatment/create/PreTreatmentCreate.qml =================================================================== diff -u -r7366dd5c970f18d53380a4e319ca94feadf25d5f -r2f0b2e204b42597e08be24df48a3b3d470b73051 --- sources/gui/qml/pages/pretreatment/create/PreTreatmentCreate.qml (.../PreTreatmentCreate.qml) (revision 7366dd5c970f18d53380a4e319ca94feadf25d5f) +++ sources/gui/qml/pages/pretreatment/create/PreTreatmentCreate.qml (.../PreTreatmentCreate.qml) (revision 2f0b2e204b42597e08be24df48a3b3d470b73051) @@ -371,6 +371,7 @@ label : qsTr("Dialysate Temperature") flickable : _flickable unit : Variables.unitTextTemperature + decimal : Variables.dialysateTempPrecision minimum : vTreatmentRanges.dialysateTempMin maximum : vTreatmentRanges.dialysateTempMax step : vTreatmentRanges.dialysateTempRes @@ -414,14 +415,19 @@ RangeSlider { id: _arterialPressureLimits objectName : "_arterialPressureLimitsSlider" // dimension - height : Variables.progressbarFluidHeight + height : Variables.sliderCreateTreatmentHeight width : Variables.createTreatmentSliderWidth diameter : Variables.sliderCircleDiameter anchors.horizontalCenter: parent.horizontalCenter ticks : true stepSnap : true hasAdjust : true + // slider visuals + showTickmarks : true + isRoundedEnds : true + isTickMarksRound: true + // Texts lowerText.visible : true lowerText.font.pixelSize : Fonts.fontPixelFluidText @@ -500,14 +506,19 @@ RangeSlider { id: _venousPressureLimits objectName: "_venousPressureLimitsSlider" // dimension - height : Variables.progressbarFluidHeight + height : Variables.sliderCreateTreatmentHeight width : Variables.createTreatmentSliderWidth diameter : Variables.sliderCircleDiameter anchors.horizontalCenter: parent.horizontalCenter ticks : true stepSnap : true hasAdjust : true + // slider visuals + showTickmarks : true + isRoundedEnds : true + isTickMarksRound: true + // Texts lowerText.visible : true lowerText.font.pixelSize : Fonts.fontPixelFluidText