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

Allow moving neighbouring thumbs to accommodate new thumb values (for issue #55) #57

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,6 @@ ext {
assertjCore1 = 'org.assertj:assertj-core:1.7.1'
assertjCore2 = 'org.assertj:assertj-core:2.5.0'
assertjCore3 = 'org.assertj:assertj-core:3.5.2'
mockitoCore = 'org.mockito:mockito-core:2.0.99-beta'
mockitoAndroid = 'org.mockito:mockito-android:2.7.22'
junit = 'junit:junit:4.12'
}
5 changes: 5 additions & 0 deletions lib/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ android {
targetSdkVersion rootProject.ext.compileSdkVersion
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}

compileOptions {
Expand All @@ -30,6 +31,10 @@ android {

dependencies {
compile rootProject.ext.supportDesign
androidTestCompile rootProject.ext.junit
androidTestCompile rootProject.ext.supportAnnotations
androidTestCompile rootProject.ext.supportTestRunner
androidTestCompile rootProject.ext.mockitoAndroid
}

apply from: 'https://raw.githubusercontent.com/djodjoni/gradle-mvn-push/master/gradle-mvn-push-android.gradle'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
package io.apptik.widget;

import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InOrder;

import static java.util.Arrays.asList;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;

@RunWith(AndroidJUnit4.class)
public class MultiSliderThumbPushTest {

private MultiSlider slider;
private MultiSlider.Thumb thumb0, thumb1, thumb2;
private MultiSlider.OnThumbValueChangeListener listener;
private InOrder listenerInOrder;

@Before
public void setup() {

slider = new MultiSlider(InstrumentationRegistry.getTargetContext());

slider.removeThumb(0);
slider.removeThumb(0);

slider.setMin(0);
slider.setMax(20);
slider.setStep(1);
slider.setStepsThumbsApart(2);

thumb0 = slider.addThumb(2);
thumb1 = slider.addThumb(6);
thumb2 = slider.addThumb(12);

listener = mock(MultiSlider.OnThumbValueChangeListener.class);
listenerInOrder = inOrder(listener);
slider.setOnThumbValueChangeListener(listener);
}

private void assertThumbValues(int expectedThumb0, int expectedThumb1, int expectedThumb2) {
assertEquals(
asList(expectedThumb0, expectedThumb1, expectedThumb2),
asList(thumb0.getValue(), thumb1.getValue(), thumb2.getValue()));
}

@Test
public void testThumbMovedBetweenSelfAndRightNeighbour() {

thumb1.setValue(8);

assertThumbValues(2, 8, 12);

listenerInOrder.verify(listener).onValueChanged(slider, thumb1, 1, 8);
listenerInOrder.verifyNoMoreInteractions();
}

@Test
public void testThumbMovedBetweenSelfAndLeftNeighbour() {

thumb2.setValue(10);

assertThumbValues(2, 6, 10);

listenerInOrder.verify(listener).onValueChanged(slider, thumb2, 2, 10);
listenerInOrder.verifyNoMoreInteractions();
}

@Test
public void testThumbMovedBetweenSelfAndRightNeighbourWithPush() {

thumb1.setValue(8, true);

assertThumbValues(2, 8, 12);

listenerInOrder.verify(listener).onValueChanged(slider, thumb1, 1, 8);
listenerInOrder.verifyNoMoreInteractions();
}

@Test
public void testThumbMovedBetweenSelfAndLeftNeighbourWithPush() {

thumb2.setValue(10, true);

assertThumbValues(2, 6, 10);

listenerInOrder.verify(listener).onValueChanged(slider, thumb2, 2, 10);
listenerInOrder.verifyNoMoreInteractions();
}

@Test
public void testThumbMovedPastRightNeighbour() {

thumb1.setValue(14);

assertThumbValues(2, 10, 12);

listenerInOrder.verify(listener).onValueChanged(slider, thumb1, 1, 10);
listenerInOrder.verifyNoMoreInteractions();
}

@Test
public void testThumbMovedPastLeftNeighbour() {

thumb1.setValue(0);

assertThumbValues(2, 4, 12);

listenerInOrder.verify(listener).onValueChanged(slider, thumb1, 1, 4);
listenerInOrder.verifyNoMoreInteractions();
}

@Test
public void testThumbMovedPastRightNeighbourWithPush() {

thumb1.setValue(14, true);

assertThumbValues(2, 14, 16);

listenerInOrder.verify(listener).onValueChanged(slider, thumb2, 2, 16);
listenerInOrder.verify(listener).onValueChanged(slider, thumb1, 1, 14);
listenerInOrder.verifyNoMoreInteractions();
}

@Test
public void testThumbMovedPastLeftNeighbourWithPush() {

thumb1.setValue(0, true);

assertThumbValues(0, 2, 12);

listenerInOrder.verify(listener).onValueChanged(slider, thumb0, 0, 0);
listenerInOrder.verify(listener).onValueChanged(slider, thumb1, 1, 2);
listenerInOrder.verifyNoMoreInteractions();
}

@Test
public void testThumbMovedPastBothRightNeighbours() {

thumb0.setValue(14);

assertThumbValues(4, 6, 12);

listenerInOrder.verify(listener).onValueChanged(slider, thumb0, 0, 4);
listenerInOrder.verifyNoMoreInteractions();
}

@Test
public void testThumbMovedPastBothLeftNeighbours() {

thumb2.setValue(0);

assertThumbValues(2, 6, 8);

listenerInOrder.verify(listener).onValueChanged(slider, thumb2, 2, 8);
listenerInOrder.verifyNoMoreInteractions();
}

@Test
public void testThumbMovedPastBothRightNeighboursWithPush() {

thumb0.setValue(14, true);

assertThumbValues(14, 16, 18);

listenerInOrder.verify(listener).onValueChanged(slider, thumb2, 2, 18);
listenerInOrder.verify(listener).onValueChanged(slider, thumb1, 1, 16);
listenerInOrder.verify(listener).onValueChanged(slider, thumb0, 0, 14);
listenerInOrder.verifyNoMoreInteractions();
}

@Test
public void testThumbMovedPastBothLeftNeighboursWithPush() {

thumb2.setValue(0, true);

assertThumbValues(0, 2, 4);

listenerInOrder.verify(listener).onValueChanged(slider, thumb0, 0, 0);
listenerInOrder.verify(listener).onValueChanged(slider, thumb1, 1, 2);
listenerInOrder.verify(listener).onValueChanged(slider, thumb2, 2, 4);
listenerInOrder.verifyNoMoreInteractions();
}
}
46 changes: 38 additions & 8 deletions lib/src/main/java/io/apptik/widget/MultiSlider.java
Original file line number Diff line number Diff line change
Expand Up @@ -312,20 +312,31 @@ public int getValue() {
}

/**
* Manually set a thumb value
* Manually set a thumb value, optionally moving neighbouring thumbs to make space.
*
* @param value
* @param pushNeighbours
* @return
*/
public Thumb setValue(int value) {
public Thumb setValue(int value, boolean pushNeighbours) {
if(mThumbs.contains(this)) {
setThumbValue(this, value, false);
setThumbValue(this, value, pushNeighbours, false);
} else {
this.value = value;
}
return this;
}

/**
* Manually set a thumb value
*
* @param value
* @return
*/
public Thumb setValue(int value) {
return setValue(value, false);
}

public String getTag() {
return tag;
}
Expand Down Expand Up @@ -788,7 +799,6 @@ private int optThumbValue(Thumb thumb, int value) {
if (thumb == null || thumb.getThumb() == null) return value;
int currIdx = mThumbs.indexOf(thumb);


if (mThumbs.size() > currIdx + 1 && value > mThumbs.get(currIdx + 1).getValue() -
mStepsThumbsApart * mStep) {
value = mThumbs.get(currIdx + 1).getValue() - mStepsThumbsApart * mStep;
Expand Down Expand Up @@ -820,11 +830,16 @@ private int optThumbValue(Thumb thumb, int value) {
*
* @param thumb the thumb which value is going to be changed
* @param value the new value
* @param fromUser if the request is coming form the user or the client
* @param fromUser if the request is coming from the user or the client
*/
private synchronized void setThumbValue(Thumb thumb, int value, boolean fromUser) {
private synchronized void setThumbValue(Thumb thumb, int value, boolean pushNeighbours,
boolean fromUser) {
if (thumb == null || thumb.getThumb() == null) return;

if (pushNeighbours) {
pushNeighbouringThumbs(thumb, value, fromUser);
}

value = optThumbValue(thumb, value);

if (value != thumb.getValue()) {
Expand All @@ -837,8 +852,23 @@ private synchronized void setThumbValue(Thumb thumb, int value, boolean fromUser
updateThumb(thumb, getWidth(), getHeight());
}

private synchronized void setThumbValue(int thumb, int value, boolean fromUser) {
setThumbValue(mThumbs.get(thumb), value, fromUser);
private synchronized void setThumbValue(Thumb thumb, int value, boolean fromUser) {
setThumbValue(thumb, value, false, fromUser);
}

private void pushNeighbouringThumbs(Thumb thumb, int value, boolean fromUser) {
int currIdx = mThumbs.indexOf(thumb);

int maxLeftValue = value - mStepsThumbsApart * mStep;
int minRightValue = value + mStepsThumbsApart * mStep;

if (currIdx > 0 && mThumbs.get(currIdx - 1).getValue() > maxLeftValue) {
setThumbValue(mThumbs.get(currIdx - 1), maxLeftValue, true, fromUser);
}

if (currIdx + 1 < mThumbs.size() && mThumbs.get(currIdx + 1).getValue() < minRightValue) {
setThumbValue(mThumbs.get(currIdx + 1), minRightValue, true, fromUser);
}
}

private void updateTrackBounds(int w, int h) {
Expand Down