Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Limiting the range #23

Open
despie opened this issue Feb 8, 2020 · 3 comments
Open

Limiting the range #23

despie opened this issue Feb 8, 2020 · 3 comments

Comments

@despie
Copy link

despie commented Feb 8, 2020

Any tip on how would you implement constraints like:

  • defining MIN and MAX allowed values (at the beginning and at the end of a circle)
  • constraining the range so that 'init' value is always less than 'end' value
  • constraining all range values not to exceed [MIN, MAX] range (meaning disabling 'laps')

For example, if a use case would be selecting time range in a single day, there is no obvious way how to achieve this.

Thanks!

@mattiadevivo
Copy link

I'm working on it, you need to put the control inside _handlePan function in circular_slider_paint file.
Anyway I've modified the slider to have four sections so my code will result different, I'm going to write some example code based on the one you can find in the repo during this weekend and I'm going to upload it here.

@mattiadevivo
Copy link

Hi, I'm sorry but I don't have enough time to write the code for your purpose, but I leave you here my code snippet about _handlePan function in circular_slider_paint file. Keep in mind I'm managing 4 handlers so the code is a little bit different but I hope useful:
`/// Handles the pan (tap)
///
/// [details] coordinates of the point where te user tapped.
/// [isPanEnd] indicates if the user stopped the pan interaction.
void _handlePan(Offset details, bool isPanEnd) {
// Retrieves the current render object for the widget.
RenderBox renderBox = context.findRenderObject();
// Get the local coordinates(on the widget) of the tap.
var position = renderBox.globalToLocal(details);

var angle = coordinatesToRadians(_painter.center, position);
var percentage = radiansToPercentage(angle);
// Int value on the slider representing the new value of the handler.
var newValue = percentageToValue(percentage, widget.divisions);

if (isBothHandlersSelected) {
  // The user is dragging a section between two handlers.
  if (_isSecondHandlerSelected && _isFirstHandlerSelected) {
    // The user is moving the section between handler #1 and #2.
    // Calculates new value for handler #1.
    var newFirstValue =
        (newValue - _differenceFromInitPoint) % widget.divisions;
    if (newFirstValue != widget.firstValue) {
      // Handler #1 is at a different position so update all the values.
      var newSecondValue =
          (widget.secondValue + (newFirstValue - widget.firstValue)) % widget.divisions;
      var newThirdValue =
          (widget.thirdValue + (newFirstValue - widget.firstValue)) % widget.divisions;
      var newFourthValue =
          (widget.fourthValue + (newFirstValue - widget.firstValue)) % widget.divisions;
      widget.onSelectionChange(
          newFirstValue, newSecondValue, newThirdValue, newFourthValue);
      if (isPanEnd) {
        widget.onSelectionEnd(
            newFirstValue, newSecondValue, newThirdValue, newFourthValue);
      }
    }
  } else if (_isThirdHandlerSelected && _isSecondHandlerSelected) {
    // The user is moving the section between handler #2 and #3.
    var newValueEnd =
        (newValue - _differenceFromInitPoint) % widget.divisions;
    if (newValueEnd != widget.secondValue) {
      var diff = newValueEnd - widget.secondValue;
      var newValueInit_2 = (widget.thirdValue + diff) % widget.divisions;
      var newValueEnd_2 = (widget.fourthValue + diff) % widget.divisions;
      var newValueInit = (widget.firstValue + diff) % widget.divisions;
      widget.onSelectionChange(
          newValueInit, newValueEnd, newValueInit_2, newValueEnd_2);
      if (isPanEnd) {
        widget.onSelectionEnd(
            newValueInit, newValueEnd, newValueInit_2, newValueEnd_2);
      }
    }
  } else if (_isFourthHandlerSelected && _isThirdHandlerSelected) {
    // The user is moving the section between handler #3 and #4.
    var newValueInit_2 =
        (newValue - _differenceFromInitPoint) % widget.divisions;
    if (newValueInit_2 != widget.thirdValue) {
      var diff = newValueInit_2 - widget.thirdValue;
      var newValueEnd_2 = (widget.fourthValue + diff) % widget.divisions;
      var newValueInit = (widget.firstValue + diff) % widget.divisions;
      var newValueEnd = (widget.secondValue + diff) % widget.divisions;
      widget.onSelectionChange(
          newValueInit, newValueEnd, newValueInit_2, newValueEnd_2);
      if (isPanEnd) {
        widget.onSelectionEnd(
            newValueInit, newValueEnd, newValueInit_2, newValueEnd_2);
      }
    }
  } else {
    // The user is moving the section between handler #4 and #1.
    var newValueEnd_2 =
        (newValue - _differenceFromInitPoint) % widget.divisions;
    if (newValueEnd_2 != widget.fourthValue) {
      var diff = newValueEnd_2 - widget.fourthValue;
      var newValueInit = (widget.firstValue + diff) % widget.divisions;
      var newValueEnd = (widget.secondValue + diff) % widget.divisions;
      var newValueInit_2 = (widget.thirdValue + diff) % widget.divisions;
      widget.onSelectionChange(
          newValueInit, newValueEnd, newValueInit_2, newValueEnd_2);
      if (isPanEnd) {
        widget.onSelectionEnd(
            newValueInit, newValueEnd, newValueInit_2, newValueEnd_2);
      }
    }
  }
  // No need to manage single handlers.
  return;
}

// isDoubleHandler but one handler was selected
if (_isFirstHandlerSelected) {
  // prec = end_2 succ = end
  if (!_isInRange(newValue, widget.fourthValue, widget.secondValue)) {
    newValue = widget.firstValue;
  }
  widget.onSelectionChange(
      newValue, widget.secondValue, widget.thirdValue, widget.fourthValue);
  if (isPanEnd) {
    widget.onSelectionEnd(
        newValue, widget.secondValue, widget.thirdValue, widget.fourthValue);
  }
} else if (_isSecondHandlerSelected) {
  // prec = init e succ = init_2
  if (!_isInRange(newValue, widget.firstValue, widget.thirdValue)) {
    newValue = widget.secondValue;
  }
  widget.onSelectionChange(
      widget.firstValue, newValue, widget.thirdValue, widget.fourthValue);
  if (isPanEnd) {
    widget.onSelectionEnd(
        widget.firstValue, newValue, widget.thirdValue, widget.fourthValue);
  }
} else if (_isThirdHandlerSelected) {
  // prec = end e succ = end_2
  if (!_isInRange(newValue, widget.secondValue, widget.fourthValue)) {
    newValue = widget.thirdValue;
  }
  widget.onSelectionChange(widget.firstValue, widget.secondValue, newValue, widget.fourthValue);
  if (isPanEnd) {
    widget.onSelectionEnd(widget.firstValue, widget.secondValue, newValue, widget.fourthValue);
  }
} else {
  //_isEnd_2HandlerSelected
  // prec = init_2 e succ = init
  if (!_isInRange(newValue, widget.thirdValue, widget.firstValue)) {
    newValue = widget.fourthValue;
  }
  widget.onSelectionChange(
      widget.firstValue, widget.secondValue, widget.thirdValue, newValue);
  if (isPanEnd) {
    widget.onSelectionEnd(widget.firstValue, widget.secondValue, widget.thirdValue, newValue);
  }
}

}

/// Returns true if value is included in the interval prec:succ, false otherwise
///
/// [value] value of the handler that was moved
/// [prev] value of the previous handler
/// [succ] value of the next handler
bool _isInRange(int value, int prev, int succ) {
if (succ < prev) {
if (succ == 0) return value > prev && value > succ;
return (value > prev && value > succ) || (value < prev && value < succ);
}
return value > prev && value < succ;
}`

@edwin-alvarez
Copy link

refer to my fork and use
minmaxValidator: MinMaxAngleValidator(
iniHandlerMinValue: 5,
iniHandlerMaxValue: 5,
endHandlerMinValue: 50,
endHandlerMaxValue: 200,

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants