Browse Source

indexed stack

Daniel Zlotin 7 years ago
parent
commit
63c5e60ca4

lib/android/app/src/main/java/com/reactnativenavigation/utils/IdStack.java → lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/IndexedStack.java View File

1
-package com.reactnativenavigation.utils;
1
+package com.reactnativenavigation.viewcontrollers;
2
+
3
+import com.reactnativenavigation.utils.StringUtils;
2
 
4
 
3
 import java.util.ArrayDeque;
5
 import java.util.ArrayDeque;
4
-import java.util.Deque;
5
 import java.util.HashMap;
6
 import java.util.HashMap;
6
 import java.util.Iterator;
7
 import java.util.Iterator;
7
-import java.util.Map;
8
 
8
 
9
-public class IdStack<E> implements Iterable<String> {
9
+public class IndexedStack<E> implements Iterable<String> {
10
 
10
 
11
 	private final ArrayDeque<String> deque = new ArrayDeque<>();
11
 	private final ArrayDeque<String> deque = new ArrayDeque<>();
12
 	private final HashMap<String, E> map = new HashMap<>();
12
 	private final HashMap<String, E> map = new HashMap<>();
63
 		return map.remove(id);
63
 		return map.remove(id);
64
 	}
64
 	}
65
 
65
 
66
+	public boolean isTop(final String id) {
67
+		return StringUtils.isEqual(id, peekId());
68
+	}
69
+
66
 	@Override
70
 	@Override
67
 	public Iterator<String> iterator() {
71
 	public Iterator<String> iterator() {
68
 		return deque.iterator();
72
 		return deque.iterator();
69
 	}
73
 	}
70
-
71
-	public Deque<String> getIds() {
72
-		return deque;
73
-	}
74
-
75
-	public Map<String, E> getMap() {
76
-		return map;
77
-	}
78
 }
74
 }

+ 14
- 28
lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/StackController.java View File

6
 import android.view.ViewGroup;
6
 import android.view.ViewGroup;
7
 import android.widget.FrameLayout;
7
 import android.widget.FrameLayout;
8
 
8
 
9
-import com.reactnativenavigation.utils.StringUtils;
10
-
11
-import java.util.ArrayDeque;
12
-import java.util.HashMap;
13
-import java.util.Map;
14
-
15
 public class StackController extends ViewController {
9
 public class StackController extends ViewController {
16
-	private final ArrayDeque<String> idStack = new ArrayDeque<>();
17
-	private final Map<String, ViewController> controllersById = new HashMap<>();
10
+	private final IndexedStack<ViewController> stack = new IndexedStack<>();
18
 
11
 
19
 	public StackController(final Activity activity, String id) {
12
 	public StackController(final Activity activity, String id) {
20
 		super(activity, id);
13
 		super(activity, id);
24
 		final ViewController previousTop = peek();
17
 		final ViewController previousTop = peek();
25
 
18
 
26
 		child.setStackController(this);
19
 		child.setStackController(this);
27
-		idStack.push(child.getId());
28
-		controllersById.put(child.getId(), child);
20
+		stack.push(child.getId(), child);
29
 
21
 
30
 		getView().addView(child.getView());
22
 		getView().addView(child.getView());
31
 		if (previousTop != null) {
23
 		if (previousTop != null) {
34
 	}
26
 	}
35
 
27
 
36
 	public boolean canPop() {
28
 	public boolean canPop() {
37
-		return idStack.size() > 1;
29
+		return stack.size() > 1;
38
 	}
30
 	}
39
 
31
 
40
 	public void pop() {
32
 	public void pop() {
41
 		if (!canPop()) {
33
 		if (!canPop()) {
42
 			return;
34
 			return;
43
 		}
35
 		}
44
-		String poppedId = idStack.pop();
45
-		ViewController poppedController = controllersById.remove(poppedId);
36
+		ViewController poppedController = stack.pop();
46
 		getView().removeView(poppedController.getView());
37
 		getView().removeView(poppedController.getView());
47
 
38
 
48
 		ViewController previousTop = peek();
39
 		ViewController previousTop = peek();
50
 	}
41
 	}
51
 
42
 
52
 	public void pop(final ViewController childController) {
43
 	public void pop(final ViewController childController) {
53
-		if (StringUtils.isEqual(peekId(), childController.getId())) {
44
+		if (stack.isTop(childController.getId())) {
54
 			pop();
45
 			pop();
55
 		} else {
46
 		} else {
56
-			idStack.remove(childController.getId());
57
-			controllersById.remove(childController.getId());
47
+			stack.remove(childController.getId());
58
 		}
48
 		}
59
 	}
49
 	}
60
 
50
 
61
 	public ViewController peek() {
51
 	public ViewController peek() {
62
-		return controllersById.get(peekId());
63
-	}
64
-
65
-	public String peekId() {
66
-		return idStack.peek();
52
+		return stack.peek();
67
 	}
53
 	}
68
 
54
 
69
 	public int size() {
55
 	public int size() {
70
-		return idStack.size();
56
+		return stack.size();
71
 	}
57
 	}
72
 
58
 
73
 	public boolean isEmpty() {
59
 	public boolean isEmpty() {
74
-		return idStack.isEmpty();
60
+		return stack.isEmpty();
75
 	}
61
 	}
76
 
62
 
77
 	@Override
63
 	@Override
103
 	}
89
 	}
104
 
90
 
105
 	public void popTo(final ViewController viewController) {
91
 	public void popTo(final ViewController viewController) {
106
-		if (!idStack.contains(viewController.getId())) {
92
+		if (!stack.containsId(viewController.getId())) {
107
 			return;
93
 			return;
108
 		}
94
 		}
109
-		while (!StringUtils.isEqual(peekId(), viewController.getId())) {
95
+		while (!stack.isTop(viewController.getId())) {
110
 			pop();
96
 			pop();
111
 		}
97
 		}
112
 	}
98
 	}
118
 	}
104
 	}
119
 
105
 
120
 	public ViewController getChildById(final String id) {
106
 	public ViewController getChildById(final String id) {
121
-		return controllersById.get(id);
107
+		return stack.get(id);
122
 	}
108
 	}
123
 
109
 
124
-	ArrayDeque<String> getStack() {
125
-		return idStack;
110
+	boolean containsId(String id) {
111
+		return stack.containsId(id);
126
 	}
112
 	}
127
 }
113
 }

lib/android/app/src/test/java/com/reactnativenavigation/utils/IndexedStackTest.java → lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/IndexedStackTest.java View File

1
-package com.reactnativenavigation.utils;
1
+package com.reactnativenavigation.viewcontrollers;
2
 
2
 
3
 import com.reactnativenavigation.BaseTest;
3
 import com.reactnativenavigation.BaseTest;
4
+import com.reactnativenavigation.viewcontrollers.IndexedStack;
4
 
5
 
5
 import org.junit.Test;
6
 import org.junit.Test;
6
 
7
 
7
-import java.util.Deque;
8
-import java.util.Map;
9
-
10
 import static org.assertj.core.api.Java6Assertions.assertThat;
8
 import static org.assertj.core.api.Java6Assertions.assertThat;
11
 
9
 
12
 public class IndexedStackTest extends BaseTest {
10
 public class IndexedStackTest extends BaseTest {
13
 
11
 
14
-	private IdStack<Integer> uut;
12
+	private IndexedStack<Integer> uut;
15
 
13
 
16
 	@Override
14
 	@Override
17
 	public void beforeEach() {
15
 	public void beforeEach() {
18
 		super.beforeEach();
16
 		super.beforeEach();
19
-		uut = new IdStack<>();
17
+		uut = new IndexedStack<>();
20
 	}
18
 	}
21
 
19
 
22
 	@Test
20
 	@Test
99
 	}
97
 	}
100
 
98
 
101
 	@Test
99
 	@Test
102
-	public void getIdDeque() throws Exception {
103
-		assertThat(uut.getIds()).isNotNull().isInstanceOf(Deque.class).isEmpty();
104
-	}
105
-
106
-	@Test
107
-	public void getMap() throws Exception {
108
-		assertThat(uut.getMap()).isNotNull().isInstanceOf(Map.class).isEmpty();
100
+	public void isTop() throws Exception {
101
+		assertThat(uut.isTop("123")).isFalse();
102
+		uut.push("123", 123);
103
+		assertThat(uut.isTop("123")).isTrue();
104
+		uut.push("456", 456);
105
+		assertThat(uut.isTop("123")).isFalse();
109
 	}
106
 	}
110
 }
107
 }

+ 19
- 12
lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/StackControllerTest.java View File

41
 		uut.push(child2);
41
 		uut.push(child2);
42
 		uut.push(child3);
42
 		uut.push(child3);
43
 		assertThat(uut.peek()).isEqualTo(child3);
43
 		assertThat(uut.peek()).isEqualTo(child3);
44
-		assertThat(uut.getStack()).containsOnly(child1.getId(), child2.getId(), child3.getId());
44
+		assertContainsOnlyId(child1.getId(), child2.getId(), child3.getId());
45
 	}
45
 	}
46
 
46
 
47
 	@Test
47
 	@Test
48
 	public void push() throws Exception {
48
 	public void push() throws Exception {
49
 		assertThat(uut.isEmpty()).isTrue();
49
 		assertThat(uut.isEmpty()).isTrue();
50
 		uut.push(child1);
50
 		uut.push(child1);
51
-		assertThat(uut.getStack()).containsOnly(child1.getId());
51
+		assertContainsOnlyId(child1.getId());
52
 	}
52
 	}
53
 
53
 
54
 	@Test
54
 	@Test
55
 	public void pop() throws Exception {
55
 	public void pop() throws Exception {
56
 		uut.push(child1);
56
 		uut.push(child1);
57
 		uut.push(child2);
57
 		uut.push(child2);
58
-		assertThat(uut.getStack()).containsOnly(child2.getId(), child1.getId());
58
+		assertContainsOnlyId(child2.getId(), child1.getId());
59
 		uut.pop();
59
 		uut.pop();
60
-		assertThat(uut.getStack()).containsOnly(child1.getId());
60
+		assertContainsOnlyId(child1.getId());
61
 	}
61
 	}
62
 
62
 
63
 	@Test
63
 	@Test
100
 
100
 
101
 	@Test
101
 	@Test
102
 	public void popDoesNothingWhenZeroOrOneChild() throws Exception {
102
 	public void popDoesNothingWhenZeroOrOneChild() throws Exception {
103
-		assertThat(uut.getStack()).isEmpty();
103
+		assertThat(uut.isEmpty()).isTrue();
104
 		uut.pop();
104
 		uut.pop();
105
-		assertThat(uut.getStack()).isEmpty();
105
+		assertThat(uut.isEmpty()).isTrue();
106
 
106
 
107
 		uut.push(child1);
107
 		uut.push(child1);
108
 		uut.pop();
108
 		uut.pop();
109
-		assertThat(uut.getStack()).containsOnly(child1.getId());
109
+		assertContainsOnlyId(child1.getId());
110
 	}
110
 	}
111
 
111
 
112
 	@Test
112
 	@Test
113
 	public void canPopWhenSizeIsMoreThanOne() throws Exception {
113
 	public void canPopWhenSizeIsMoreThanOne() throws Exception {
114
-		assertThat(uut.getStack()).isEmpty();
114
+		assertThat(uut.isEmpty()).isTrue();
115
 		assertThat(uut.canPop()).isFalse();
115
 		assertThat(uut.canPop()).isFalse();
116
 		uut.push(child1);
116
 		uut.push(child1);
117
-		assertThat(uut.getStack()).containsOnly(child1.getId());
117
+		assertContainsOnlyId(child1.getId());
118
 		assertThat(uut.canPop()).isFalse();
118
 		assertThat(uut.canPop()).isFalse();
119
 		uut.push(child2);
119
 		uut.push(child2);
120
-		assertThat(uut.getStack()).containsOnly(child1.getId(), child2.getId());
120
+		assertContainsOnlyId(child1.getId(), child2.getId());
121
 		assertThat(uut.canPop()).isTrue();
121
 		assertThat(uut.canPop()).isTrue();
122
 	}
122
 	}
123
 
123
 
159
 		uut.push(child1);
159
 		uut.push(child1);
160
 		uut.push(child2);
160
 		uut.push(child2);
161
 		uut.pop(child2);
161
 		uut.pop(child2);
162
-		assertThat(uut.getStack()).containsOnly(child1.getId());
162
+		assertContainsOnlyId(child1.getId());
163
 		assertHasSingleChildViewOfController(child1);
163
 		assertHasSingleChildViewOfController(child1);
164
 	}
164
 	}
165
 
165
 
170
 		assertHasSingleChildViewOfController(child2);
170
 		assertHasSingleChildViewOfController(child2);
171
 
171
 
172
 		uut.pop(child1);
172
 		uut.pop(child1);
173
-		assertThat(uut.getStack()).containsOnly(child2.getId());
173
+		assertContainsOnlyId(child2.getId());
174
 		assertHasSingleChildViewOfController(child2);
174
 		assertHasSingleChildViewOfController(child2);
175
 	}
175
 	}
176
 
176
 
236
 		assertThat(uut.getView().getChildCount()).isEqualTo(1);
236
 		assertThat(uut.getView().getChildCount()).isEqualTo(1);
237
 		assertThat(uut.getView().getChildAt(0)).isEqualTo(childController.getView());
237
 		assertThat(uut.getView().getChildAt(0)).isEqualTo(childController.getView());
238
 	}
238
 	}
239
+
240
+	private void assertContainsOnlyId(String... ids) {
241
+		assertThat(uut.size()).isEqualTo(ids.length);
242
+		for (String id : ids) {
243
+			assertThat(uut.containsId(id));
244
+		}
245
+	}
239
 }
246
 }