Browse Source

Removed NavigationOptionsListener

This commit removes NavigationOptionsListener as it was not needed anymore.
As a result, it uncovered a few issues which this commit also aims to fix.

* Set SideMenuController as parent of left, right and centre controllers
* Select tab by id with tabSelector interface
* mergeOptions now also applies options after merge - in ViewController base class
* Pull presentation logic from ComponentLayout to ComponentViewController
Guy Carmeli 6 years ago
parent
commit
6a69287242
26 changed files with 277 additions and 299 deletions
  1. 8
    7
      lib/android/app/src/main/java/com/reactnativenavigation/parse/LayoutFactory.java
  2. 2
    1
      lib/android/app/src/main/java/com/reactnativenavigation/presentation/BottomTabsOptionsPresenter.java
  3. 0
    31
      lib/android/app/src/main/java/com/reactnativenavigation/presentation/ComponentOptionsPresenter.java
  4. 0
    8
      lib/android/app/src/main/java/com/reactnativenavigation/presentation/NavigationOptionsListener.java
  5. 11
    166
      lib/android/app/src/main/java/com/reactnativenavigation/presentation/OptionsPresenter.java
  6. 187
    0
      lib/android/app/src/main/java/com/reactnativenavigation/presentation/StackOptionsPresenter.java
  7. 3
    4
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/ComponentViewController.java
  8. 2
    6
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/Navigator.java
  9. 11
    4
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/SideMenuController.java
  10. 0
    5
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/StackController.java
  11. 12
    1
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/ViewController.java
  12. 1
    8
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/bottomtabs/BottomTabsController.java
  13. 0
    5
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/externalcomponent/ExternalComponentViewController.java
  14. 1
    7
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/toptabs/TopTabsController.java
  15. 0
    3
      lib/android/app/src/main/java/com/reactnativenavigation/views/Component.java
  16. 0
    5
      lib/android/app/src/main/java/com/reactnativenavigation/views/ComponentLayout.java
  17. 0
    7
      lib/android/app/src/main/java/com/reactnativenavigation/views/ExternalComponentLayout.java
  18. 3
    3
      lib/android/app/src/main/java/com/reactnativenavigation/views/StackLayout.java
  19. 4
    5
      lib/android/app/src/main/java/com/reactnativenavigation/views/toptabs/TopTabsViewPager.java
  20. 8
    6
      lib/android/app/src/test/java/com/reactnativenavigation/mocks/SimpleViewController.java
  21. 0
    2
      lib/android/app/src/test/java/com/reactnativenavigation/parse/OptionsTest.java
  22. 16
    1
      lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/BottomTabsControllerTest.java
  23. 3
    3
      lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/OptionsMergingTest.java
  24. 3
    3
      lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/SideMenuControllerTest.java
  25. 1
    8
      playground/src/screens/TextScreen.js
  26. 1
    0
      playground/src/screens/WelcomeScreen.js

+ 8
- 7
lib/android/app/src/main/java/com/reactnativenavigation/parse/LayoutFactory.java View File

72
 	}
72
 	}
73
 
73
 
74
     private ViewController createSideMenuRoot(LayoutNode node) {
74
     private ViewController createSideMenuRoot(LayoutNode node) {
75
-        SideMenuController sideMenuLayout = new SideMenuController(activity, node.id, getOptions(node));
75
+        SideMenuController sideMenuController = new SideMenuController(activity, node.id, getOptions(node));
76
 		for (LayoutNode child : node.children) {
76
 		for (LayoutNode child : node.children) {
77
-			ViewController childLayout = create(child);
77
+			ViewController childController = create(child);
78
+            childController.setParentController(sideMenuController);
78
 			switch (child.type) {
79
 			switch (child.type) {
79
 				case SideMenuCenter:
80
 				case SideMenuCenter:
80
-					sideMenuLayout.setCenterController(childLayout);
81
+					sideMenuController.setCenterController(childController);
81
 					break;
82
 					break;
82
 				case SideMenuLeft:
83
 				case SideMenuLeft:
83
-					sideMenuLayout.setLeftController(childLayout);
84
+					sideMenuController.setLeftController(childController);
84
 					break;
85
 					break;
85
 				case SideMenuRight:
86
 				case SideMenuRight:
86
-					sideMenuLayout.setRightController(childLayout);
87
+					sideMenuController.setRightController(childController);
87
 					break;
88
 					break;
88
 				default:
89
 				default:
89
 					throw new IllegalArgumentException("Invalid node type in sideMenu: " + node.type);
90
 					throw new IllegalArgumentException("Invalid node type in sideMenu: " + node.type);
90
 			}
91
 			}
91
-		}
92
-		return sideMenuLayout;
92
+        }
93
+		return sideMenuController;
93
 	}
94
 	}
94
 
95
 
95
 	private ViewController createSideMenuContent(LayoutNode node) {
96
 	private ViewController createSideMenuContent(LayoutNode node) {

+ 2
- 1
lib/android/app/src/main/java/com/reactnativenavigation/presentation/BottomTabsOptionsPresenter.java View File

27
     }
27
     }
28
 
28
 
29
     public void present(Options options, int tabIndex) {
29
     public void present(Options options, int tabIndex) {
30
+        applyBottomTabsOptions(options.bottomTabsOptions, options.animations);
30
         applyBottomTabOptions(options.bottomTabOptions, tabIndex);
31
         applyBottomTabOptions(options.bottomTabOptions, tabIndex);
31
     }
32
     }
32
 
33
 
55
         }
56
         }
56
         if (options.currentTabId.hasValue()) {
57
         if (options.currentTabId.hasValue()) {
57
             int tabIndex = bottomTabFinder.findByControllerId(options.currentTabId.get());
58
             int tabIndex = bottomTabFinder.findByControllerId(options.currentTabId.get());
58
-            if (tabIndex >= 0) bottomTabs.setCurrentItem(tabIndex);
59
+            if (tabIndex >= 0) tabSelector.selectTab(tabIndex);
59
         }
60
         }
60
         if (options.visible.isTrueOrUndefined()) {
61
         if (options.visible.isTrueOrUndefined()) {
61
             if (options.animate.isTrueOrUndefined()) {
62
             if (options.animate.isTrueOrUndefined()) {

+ 0
- 31
lib/android/app/src/main/java/com/reactnativenavigation/presentation/ComponentOptionsPresenter.java View File

1
-package com.reactnativenavigation.presentation;
2
-
3
-import android.app.Activity;
4
-import android.view.View;
5
-
6
-import com.reactnativenavigation.parse.Options;
7
-import com.reactnativenavigation.parse.OrientationOptions;
8
-
9
-public class ComponentOptionsPresenter {
10
-    private View component;
11
-
12
-    public ComponentOptionsPresenter(View component) {
13
-        this.component = component;
14
-    }
15
-
16
-    public void present(Options options) {
17
-        applyOrientation(options.orientationOptions);
18
-        applyOtherOptions(options);
19
-    }
20
-
21
-    private void applyOrientation(OrientationOptions options) {
22
-        ((Activity) component.getContext()).setRequestedOrientation(options.getValue());
23
-    }
24
-
25
-    private void applyOtherOptions(Options options) {
26
-        if (options.screenBackgroundColor.hasValue()) {
27
-            component.setBackgroundColor(options.screenBackgroundColor.get());
28
-        }
29
-    }
30
-
31
-}

+ 0
- 8
lib/android/app/src/main/java/com/reactnativenavigation/presentation/NavigationOptionsListener.java View File

1
-package com.reactnativenavigation.presentation;
2
-
3
-
4
-import com.reactnativenavigation.parse.Options;
5
-
6
-public interface NavigationOptionsListener {
7
-	void mergeOptions(Options options);
8
-}

+ 11
- 166
lib/android/app/src/main/java/com/reactnativenavigation/presentation/OptionsPresenter.java View File

1
 package com.reactnativenavigation.presentation;
1
 package com.reactnativenavigation.presentation;
2
 
2
 
3
 import android.app.Activity;
3
 import android.app.Activity;
4
-import android.graphics.Color;
4
+import android.view.View;
5
 
5
 
6
-import com.reactnativenavigation.parse.AnimationsOptions;
7
 import com.reactnativenavigation.parse.Options;
6
 import com.reactnativenavigation.parse.Options;
8
 import com.reactnativenavigation.parse.OrientationOptions;
7
 import com.reactnativenavigation.parse.OrientationOptions;
9
-import com.reactnativenavigation.parse.TopBarOptions;
10
-import com.reactnativenavigation.parse.TopTabOptions;
11
-import com.reactnativenavigation.parse.TopTabsOptions;
12
-import com.reactnativenavigation.parse.params.Button;
13
-import com.reactnativenavigation.utils.UiUtils;
14
-import com.reactnativenavigation.viewcontrollers.IReactView;
15
-import com.reactnativenavigation.views.Component;
16
-import com.reactnativenavigation.views.topbar.TopBar;
17
-
18
-import java.util.ArrayList;
19
 
8
 
20
 public class OptionsPresenter {
9
 public class OptionsPresenter {
21
-    private static final int DEFAULT_TITLE_COLOR = Color.BLACK;
22
-    private static final int DEFAULT_SUBTITLE_COLOR = Color.GRAY;
23
-    private final float defaultTitleFontSize;
24
-    private final float defaultSubtitleFontSize;
25
 
10
 
26
-    private TopBar topBar;
11
+    private Activity activity;
27
 
12
 
28
-    public OptionsPresenter(TopBar topBar) {
29
-        this.topBar = topBar;
30
-        defaultTitleFontSize = UiUtils.dpToSp(topBar.getContext(), 18);
31
-        defaultSubtitleFontSize = UiUtils.dpToSp(topBar.getContext(), 14);
13
+    public OptionsPresenter(Activity activity) {
14
+        this.activity = activity;
32
     }
15
     }
33
 
16
 
34
-    public void applyChildOptions(Options options, Component child) {
17
+    public void present(View view, Options options) {
35
         applyOrientation(options.orientationOptions);
18
         applyOrientation(options.orientationOptions);
36
-        applyButtons(options.topBar.leftButtons, options.topBar.rightButtons);
37
-        applyTopBarOptions(options.topBar, options.animations, child, options);
38
-        applyTopTabsOptions(options.topTabsOptions);
39
-        applyTopTabOptions(options.topTabOptions);
19
+        applyViewOptions(view, options);
40
     }
20
     }
41
 
21
 
42
-    public void applyOrientation(OrientationOptions options) {
43
-        ((Activity) topBar.getContext()).setRequestedOrientation(options.getValue());
22
+    private void applyOrientation(OrientationOptions options) {
23
+        activity.setRequestedOrientation(options.getValue());
44
     }
24
     }
45
 
25
 
46
-    private void applyTopBarOptions(TopBarOptions options, AnimationsOptions animationOptions, Component component, Options componentOptions) {
47
-        topBar.setTitle(options.title.text.get(""));
48
-        if (options.title.component.hasValue()) topBar.setTitleComponent(options.title.component);
49
-        topBar.setTitleFontSize(options.title.fontSize.get(defaultTitleFontSize));
50
-        topBar.setTitleTextColor(options.title.color.get(DEFAULT_TITLE_COLOR));
51
-        topBar.setTitleTypeface(options.title.fontFamily);
52
-        topBar.setTitleAlignment(options.title.alignment);
53
-
54
-        topBar.setSubtitle(options.subtitle.text.get(""));
55
-        topBar.setSubtitleFontSize(options.subtitle.fontSize.get(defaultSubtitleFontSize));
56
-        topBar.setSubtitleColor(options.subtitle.color.get(DEFAULT_SUBTITLE_COLOR));
57
-        topBar.setSubtitleFontFamily(options.subtitle.fontFamily);
58
-        topBar.setSubtitleAlignment(options.subtitle.alignment);
59
-
60
-        topBar.setBackgroundColor(options.background.color);
61
-        topBar.setBackgroundComponent(options.background.component);
62
-        if (options.testId.hasValue()) topBar.setTestId(options.testId.get());
63
-
64
-        if (options.visible.isFalse()) {
65
-            if (options.animate.isTrueOrUndefined() && componentOptions.animations.push.enable.isTrueOrUndefined()) {
66
-                topBar.hideAnimate(animationOptions.pop.topBar);
67
-            } else {
68
-                topBar.hide();
69
-            }
70
-        }
71
-        if (options.visible.isTrueOrUndefined()) {
72
-            if (options.animate.isTrueOrUndefined() && componentOptions.animations.push.enable.isTrueOrUndefined()) {
73
-                topBar.showAnimate(animationOptions.push.topBar);
74
-            } else {
75
-                topBar.show();
76
-            }
77
-        }
78
-        if (options.drawBehind.isTrue()) {
79
-            component.drawBehindTopBar();
80
-        } else if (options.drawBehind.isFalseOrUndefined()) {
81
-            component.drawBelowTopBar(topBar);
82
-        }
83
-        if (options.hideOnScroll.isTrue()) {
84
-            if (component instanceof IReactView) {
85
-                topBar.enableCollapse(((IReactView) component).getScrollEventListener());
86
-            }
87
-        } else if (options.hideOnScroll.isFalseOrUndefined()) {
88
-            topBar.disableCollapse();
26
+    private void applyViewOptions(View view, Options options) {
27
+        if (options.screenBackgroundColor.hasValue()) {
28
+            view.setBackgroundColor(options.screenBackgroundColor.get());
89
         }
29
         }
90
     }
30
     }
91
 
31
 
92
-    private void applyButtons(ArrayList<Button> leftButtons, ArrayList<Button> rightButtons) {
93
-        topBar.setLeftButtons(leftButtons);
94
-        topBar.setRightButtons(rightButtons);
95
-    }
96
-
97
-    private void applyTopTabsOptions(TopTabsOptions options) {
98
-        topBar.applyTopTabsColors(options.selectedTabColor, options.unselectedTabColor);
99
-        topBar.applyTopTabsFontSize(options.fontSize);
100
-        topBar.setTopTabsVisible(options.visible.isTrueOrUndefined());
101
-    }
102
-
103
-    private void applyTopTabOptions(TopTabOptions topTabOptions) {
104
-        if (topTabOptions.fontFamily != null) topBar.setTopTabFontFamily(topTabOptions.tabIndex, topTabOptions.fontFamily);
105
-    }
106
-
107
-    public void onChildWillAppear(Options appearing, Options disappearing) {
108
-        if (disappearing.topBar.visible.isTrueOrUndefined() && appearing.topBar.visible.isFalse()) {
109
-            if (disappearing.topBar.animate.isTrueOrUndefined() && disappearing.animations.pop.enable.isTrueOrUndefined()) {
110
-                topBar.hideAnimate(disappearing.animations.pop.topBar);
111
-            } else {
112
-                topBar.hide();
113
-            }
114
-        }
115
-    }
116
-
117
-    public void mergeChildOptions(Options options, Component child) {
118
-        mergeOrientation(options.orientationOptions);
119
-        mergeButtons(options.topBar.leftButtons, options.topBar.rightButtons);
120
-        mergeTopBarOptions(options.topBar, options.animations, child);
121
-        mergeTopTabsOptions(options.topTabsOptions);
122
-        mergeTopTabOptions(options.topTabOptions);
123
-    }
124
-
125
-    private void mergeOrientation(OrientationOptions orientationOptions) {
126
-        if (orientationOptions.hasValue()) applyOrientation(orientationOptions);
127
-    }
128
-
129
-    private void mergeButtons(ArrayList<Button> leftButtons, ArrayList<Button> rightButtons) {
130
-        if (leftButtons != null) topBar.setLeftButtons(leftButtons);
131
-        if (rightButtons != null) topBar.setRightButtons(rightButtons);
132
-    }
133
-
134
-    private void mergeTopBarOptions(TopBarOptions options, AnimationsOptions animationsOptions, Component component) {
135
-        if (options.title.text.hasValue()) topBar.setTitle(options.title.text.get());
136
-        if (options.title.component.hasValue()) topBar.setTitleComponent(options.title.component);
137
-        if (options.title.color.hasValue()) topBar.setTitleTextColor(options.title.color.get());
138
-        if (options.title.fontSize.hasValue()) topBar.setTitleFontSize(options.title.fontSize.get());
139
-        if (options.title.fontFamily != null) topBar.setTitleTypeface(options.title.fontFamily);
140
-
141
-        if (options.subtitle.text.hasValue()) topBar.setSubtitle(options.subtitle.text.get());
142
-        if (options.subtitle.color.hasValue()) topBar.setSubtitleColor(options.subtitle.color.get());
143
-        if (options.subtitle.fontSize.hasValue()) topBar.setSubtitleFontSize(options.subtitle.fontSize.get());
144
-        if (options.subtitle.fontFamily != null) topBar.setSubtitleFontFamily(options.subtitle.fontFamily);
145
-
146
-        if (options.background.color.hasValue()) topBar.setBackgroundColor(options.background.color);
147
-
148
-        if (options.testId.hasValue()) topBar.setTestId(options.testId.get());
149
-
150
-        if (options.visible.isFalse()) {
151
-            if (options.animate.isTrueOrUndefined()) {
152
-                topBar.hideAnimate(animationsOptions.pop.topBar);
153
-            } else {
154
-                topBar.hide();
155
-            }
156
-        }
157
-        if (options.visible.isTrue()) {
158
-            if (options.animate.isTrueOrUndefined()) {
159
-                topBar.showAnimate(animationsOptions.push.topBar);
160
-            } else {
161
-                topBar.show();
162
-            }
163
-        }
164
-        if (options.drawBehind.isTrue()) {
165
-            component.drawBehindTopBar();
166
-        }
167
-        if (options.drawBehind.isFalse()) {
168
-            component.drawBelowTopBar(topBar);
169
-        }
170
-        if (options.hideOnScroll.isTrue() && component instanceof IReactView) {
171
-            topBar.enableCollapse(((IReactView) component).getScrollEventListener());
172
-        }
173
-        if (options.hideOnScroll.isFalse()) {
174
-            topBar.disableCollapse();
175
-        }
176
-    }
177
-
178
-    private void mergeTopTabsOptions(TopTabsOptions options) {
179
-        if (options.selectedTabColor.hasValue() && options.unselectedTabColor.hasValue()) topBar.applyTopTabsColors(options.selectedTabColor, options.unselectedTabColor);
180
-        if (options.fontSize.hasValue()) topBar.applyTopTabsFontSize(options.fontSize);
181
-        if (options.visible.hasValue()) topBar.setTopTabsVisible(options.visible.isTrue());
182
-    }
183
-
184
-    private void mergeTopTabOptions(TopTabOptions topTabOptions) {
185
-        if (topTabOptions.fontFamily != null) topBar.setTopTabFontFamily(topTabOptions.tabIndex, topTabOptions.fontFamily);
186
-    }
187
 }
32
 }

+ 187
- 0
lib/android/app/src/main/java/com/reactnativenavigation/presentation/StackOptionsPresenter.java View File

1
+package com.reactnativenavigation.presentation;
2
+
3
+import android.app.Activity;
4
+import android.graphics.Color;
5
+
6
+import com.reactnativenavigation.parse.AnimationsOptions;
7
+import com.reactnativenavigation.parse.Options;
8
+import com.reactnativenavigation.parse.OrientationOptions;
9
+import com.reactnativenavigation.parse.TopBarOptions;
10
+import com.reactnativenavigation.parse.TopTabOptions;
11
+import com.reactnativenavigation.parse.TopTabsOptions;
12
+import com.reactnativenavigation.parse.params.Button;
13
+import com.reactnativenavigation.utils.UiUtils;
14
+import com.reactnativenavigation.viewcontrollers.IReactView;
15
+import com.reactnativenavigation.views.Component;
16
+import com.reactnativenavigation.views.topbar.TopBar;
17
+
18
+import java.util.ArrayList;
19
+
20
+public class StackOptionsPresenter {
21
+    private static final int DEFAULT_TITLE_COLOR = Color.BLACK;
22
+    private static final int DEFAULT_SUBTITLE_COLOR = Color.GRAY;
23
+    private final float defaultTitleFontSize;
24
+    private final float defaultSubtitleFontSize;
25
+
26
+    private TopBar topBar;
27
+
28
+    public StackOptionsPresenter(TopBar topBar) {
29
+        this.topBar = topBar;
30
+        defaultTitleFontSize = UiUtils.dpToSp(topBar.getContext(), 18);
31
+        defaultSubtitleFontSize = UiUtils.dpToSp(topBar.getContext(), 14);
32
+    }
33
+
34
+    public void applyChildOptions(Options options, Component child) {
35
+        applyOrientation(options.orientationOptions);
36
+        applyButtons(options.topBar.leftButtons, options.topBar.rightButtons);
37
+        applyTopBarOptions(options.topBar, options.animations, child, options);
38
+        applyTopTabsOptions(options.topTabsOptions);
39
+        applyTopTabOptions(options.topTabOptions);
40
+    }
41
+
42
+    public void applyOrientation(OrientationOptions options) {
43
+        ((Activity) topBar.getContext()).setRequestedOrientation(options.getValue());
44
+    }
45
+
46
+    private void applyTopBarOptions(TopBarOptions options, AnimationsOptions animationOptions, Component component, Options componentOptions) {
47
+        topBar.setTitle(options.title.text.get(""));
48
+        if (options.title.component.hasValue()) topBar.setTitleComponent(options.title.component);
49
+        topBar.setTitleFontSize(options.title.fontSize.get(defaultTitleFontSize));
50
+        topBar.setTitleTextColor(options.title.color.get(DEFAULT_TITLE_COLOR));
51
+        topBar.setTitleTypeface(options.title.fontFamily);
52
+        topBar.setTitleAlignment(options.title.alignment);
53
+
54
+        topBar.setSubtitle(options.subtitle.text.get(""));
55
+        topBar.setSubtitleFontSize(options.subtitle.fontSize.get(defaultSubtitleFontSize));
56
+        topBar.setSubtitleColor(options.subtitle.color.get(DEFAULT_SUBTITLE_COLOR));
57
+        topBar.setSubtitleFontFamily(options.subtitle.fontFamily);
58
+        topBar.setSubtitleAlignment(options.subtitle.alignment);
59
+
60
+        topBar.setBackgroundColor(options.background.color);
61
+        topBar.setBackgroundComponent(options.background.component);
62
+        if (options.testId.hasValue()) topBar.setTestId(options.testId.get());
63
+
64
+        if (options.visible.isFalse()) {
65
+            if (options.animate.isTrueOrUndefined() && componentOptions.animations.push.enable.isTrueOrUndefined()) {
66
+                topBar.hideAnimate(animationOptions.pop.topBar);
67
+            } else {
68
+                topBar.hide();
69
+            }
70
+        }
71
+        if (options.visible.isTrueOrUndefined()) {
72
+            if (options.animate.isTrueOrUndefined() && componentOptions.animations.push.enable.isTrueOrUndefined()) {
73
+                topBar.showAnimate(animationOptions.push.topBar);
74
+            } else {
75
+                topBar.show();
76
+            }
77
+        }
78
+        if (options.drawBehind.isTrue()) {
79
+            component.drawBehindTopBar();
80
+        } else if (options.drawBehind.isFalseOrUndefined()) {
81
+            component.drawBelowTopBar(topBar);
82
+        }
83
+        if (options.hideOnScroll.isTrue()) {
84
+            if (component instanceof IReactView) {
85
+                topBar.enableCollapse(((IReactView) component).getScrollEventListener());
86
+            }
87
+        } else if (options.hideOnScroll.isFalseOrUndefined()) {
88
+            topBar.disableCollapse();
89
+        }
90
+    }
91
+
92
+    private void applyButtons(ArrayList<Button> leftButtons, ArrayList<Button> rightButtons) {
93
+        topBar.setLeftButtons(leftButtons);
94
+        topBar.setRightButtons(rightButtons);
95
+    }
96
+
97
+    private void applyTopTabsOptions(TopTabsOptions options) {
98
+        topBar.applyTopTabsColors(options.selectedTabColor, options.unselectedTabColor);
99
+        topBar.applyTopTabsFontSize(options.fontSize);
100
+        topBar.setTopTabsVisible(options.visible.isTrueOrUndefined());
101
+    }
102
+
103
+    private void applyTopTabOptions(TopTabOptions topTabOptions) {
104
+        if (topTabOptions.fontFamily != null) topBar.setTopTabFontFamily(topTabOptions.tabIndex, topTabOptions.fontFamily);
105
+    }
106
+
107
+    public void onChildWillAppear(Options appearing, Options disappearing) {
108
+        if (disappearing.topBar.visible.isTrueOrUndefined() && appearing.topBar.visible.isFalse()) {
109
+            if (disappearing.topBar.animate.isTrueOrUndefined() && disappearing.animations.pop.enable.isTrueOrUndefined()) {
110
+                topBar.hideAnimate(disappearing.animations.pop.topBar);
111
+            } else {
112
+                topBar.hide();
113
+            }
114
+        }
115
+    }
116
+
117
+    public void mergeChildOptions(Options options, Component child) {
118
+        mergeOrientation(options.orientationOptions);
119
+        mergeButtons(options.topBar.leftButtons, options.topBar.rightButtons);
120
+        mergeTopBarOptions(options.topBar, options.animations, child);
121
+        mergeTopTabsOptions(options.topTabsOptions);
122
+        mergeTopTabOptions(options.topTabOptions);
123
+    }
124
+
125
+    private void mergeOrientation(OrientationOptions orientationOptions) {
126
+        if (orientationOptions.hasValue()) applyOrientation(orientationOptions);
127
+    }
128
+
129
+    private void mergeButtons(ArrayList<Button> leftButtons, ArrayList<Button> rightButtons) {
130
+        if (leftButtons != null) topBar.setLeftButtons(leftButtons);
131
+        if (rightButtons != null) topBar.setRightButtons(rightButtons);
132
+    }
133
+
134
+    private void mergeTopBarOptions(TopBarOptions options, AnimationsOptions animationsOptions, Component component) {
135
+        if (options.title.text.hasValue()) topBar.setTitle(options.title.text.get());
136
+        if (options.title.component.hasValue()) topBar.setTitleComponent(options.title.component);
137
+        if (options.title.color.hasValue()) topBar.setTitleTextColor(options.title.color.get());
138
+        if (options.title.fontSize.hasValue()) topBar.setTitleFontSize(options.title.fontSize.get());
139
+        if (options.title.fontFamily != null) topBar.setTitleTypeface(options.title.fontFamily);
140
+
141
+        if (options.subtitle.text.hasValue()) topBar.setSubtitle(options.subtitle.text.get());
142
+        if (options.subtitle.color.hasValue()) topBar.setSubtitleColor(options.subtitle.color.get());
143
+        if (options.subtitle.fontSize.hasValue()) topBar.setSubtitleFontSize(options.subtitle.fontSize.get());
144
+        if (options.subtitle.fontFamily != null) topBar.setSubtitleFontFamily(options.subtitle.fontFamily);
145
+
146
+        if (options.background.color.hasValue()) topBar.setBackgroundColor(options.background.color);
147
+
148
+        if (options.testId.hasValue()) topBar.setTestId(options.testId.get());
149
+
150
+        if (options.visible.isFalse()) {
151
+            if (options.animate.isTrueOrUndefined()) {
152
+                topBar.hideAnimate(animationsOptions.pop.topBar);
153
+            } else {
154
+                topBar.hide();
155
+            }
156
+        }
157
+        if (options.visible.isTrue()) {
158
+            if (options.animate.isTrueOrUndefined()) {
159
+                topBar.showAnimate(animationsOptions.push.topBar);
160
+            } else {
161
+                topBar.show();
162
+            }
163
+        }
164
+        if (options.drawBehind.isTrue()) {
165
+            component.drawBehindTopBar();
166
+        }
167
+        if (options.drawBehind.isFalse()) {
168
+            component.drawBelowTopBar(topBar);
169
+        }
170
+        if (options.hideOnScroll.isTrue() && component instanceof IReactView) {
171
+            topBar.enableCollapse(((IReactView) component).getScrollEventListener());
172
+        }
173
+        if (options.hideOnScroll.isFalse()) {
174
+            topBar.disableCollapse();
175
+        }
176
+    }
177
+
178
+    private void mergeTopTabsOptions(TopTabsOptions options) {
179
+        if (options.selectedTabColor.hasValue() && options.unselectedTabColor.hasValue()) topBar.applyTopTabsColors(options.selectedTabColor, options.unselectedTabColor);
180
+        if (options.fontSize.hasValue()) topBar.applyTopTabsFontSize(options.fontSize);
181
+        if (options.visible.hasValue()) topBar.setTopTabsVisible(options.visible.isTrue());
182
+    }
183
+
184
+    private void mergeTopTabOptions(TopTabOptions topTabOptions) {
185
+        if (topTabOptions.fontFamily != null) topBar.setTopTabFontFamily(topTabOptions.tabIndex, topTabOptions.fontFamily);
186
+    }
187
+}

+ 3
- 4
lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/ComponentViewController.java View File

4
 import android.support.annotation.NonNull;
4
 import android.support.annotation.NonNull;
5
 
5
 
6
 import com.reactnativenavigation.parse.Options;
6
 import com.reactnativenavigation.parse.Options;
7
-import com.reactnativenavigation.presentation.NavigationOptionsListener;
8
 import com.reactnativenavigation.views.ComponentLayout;
7
 import com.reactnativenavigation.views.ComponentLayout;
9
 import com.reactnativenavigation.views.ReactComponent;
8
 import com.reactnativenavigation.views.ReactComponent;
10
 
9
 
11
-public class ComponentViewController extends ViewController<ComponentLayout> implements NavigationOptionsListener {
10
+public class ComponentViewController extends ViewController<ComponentLayout> {
12
 
11
 
13
     private final String componentName;
12
     private final String componentName;
14
 
13
 
43
 
42
 
44
     @Override
43
     @Override
45
     public void applyOptions(Options options) {
44
     public void applyOptions(Options options) {
45
+        super.applyOptions(options);
46
         view.applyOptions(options);
46
         view.applyOptions(options);
47
     }
47
     }
48
 
48
 
60
 
60
 
61
     @Override
61
     @Override
62
     public void mergeOptions(Options options) {
62
     public void mergeOptions(Options options) {
63
-        view.applyOptions(options);
64
         applyOnParentController(parentController -> parentController.mergeChildOptions(options, view));
63
         applyOnParentController(parentController -> parentController.mergeChildOptions(options, view));
65
-        this.options = this.options.mergeWith(options);
64
+        super.mergeOptions(options);
66
     }
65
     }
67
 
66
 
68
     ReactComponent getComponent() {
67
     ReactComponent getComponent() {

+ 2
- 6
lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/Navigator.java View File

11
 import com.reactnativenavigation.anim.ModalAnimator;
11
 import com.reactnativenavigation.anim.ModalAnimator;
12
 import com.reactnativenavigation.anim.NavigationAnimator;
12
 import com.reactnativenavigation.anim.NavigationAnimator;
13
 import com.reactnativenavigation.parse.Options;
13
 import com.reactnativenavigation.parse.Options;
14
-import com.reactnativenavigation.presentation.NavigationOptionsListener;
15
 import com.reactnativenavigation.presentation.OverlayManager;
14
 import com.reactnativenavigation.presentation.OverlayManager;
16
 import com.reactnativenavigation.react.JsDevReloadHandler;
15
 import com.reactnativenavigation.react.JsDevReloadHandler;
17
 import com.reactnativenavigation.utils.CommandListener;
16
 import com.reactnativenavigation.utils.CommandListener;
119
 
118
 
120
     public void mergeOptions(final String componentId, Options options) {
119
     public void mergeOptions(final String componentId, Options options) {
121
         ViewController target = findControllerById(componentId);
120
         ViewController target = findControllerById(componentId);
122
-        if (target instanceof NavigationOptionsListener) {
123
-            ((NavigationOptionsListener) target).mergeOptions(options);
124
-        }
125
-        if (root instanceof NavigationOptionsListener) {
126
-            ((NavigationOptionsListener) root).mergeOptions(options);
121
+        if (target != null) {
122
+            target.mergeOptions(options);
127
         }
123
         }
128
     }
124
     }
129
 
125
 

+ 11
- 4
lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/SideMenuController.java View File

8
 import android.view.View;
8
 import android.view.View;
9
 
9
 
10
 import com.reactnativenavigation.parse.Options;
10
 import com.reactnativenavigation.parse.Options;
11
-import com.reactnativenavigation.presentation.NavigationOptionsListener;
12
 import com.reactnativenavigation.presentation.SideMenuOptionsPresenter;
11
 import com.reactnativenavigation.presentation.SideMenuOptionsPresenter;
13
 import com.reactnativenavigation.views.Component;
12
 import com.reactnativenavigation.views.Component;
14
 
13
 
17
 
16
 
18
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
17
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
19
 
18
 
20
-public class SideMenuController extends ParentController<DrawerLayout> implements NavigationOptionsListener {
19
+public class SideMenuController extends ParentController<DrawerLayout> {
21
 
20
 
22
 	private ViewController centerController;
21
 	private ViewController centerController;
23
 	private ViewController leftController;
22
 	private ViewController leftController;
56
         );
55
         );
57
     }
56
     }
58
 
57
 
58
+    @Override
59
+    public void mergeChildOptions(Options options, Component child) {
60
+        super.mergeChildOptions(options, child);
61
+        new SideMenuOptionsPresenter(getView()).present(options.sideMenuRootOptions);
62
+        applyOnParentController(parentController ->
63
+                ((ParentController) parentController).mergeChildOptions(options.copy().clearSideMenuOptions(), child)
64
+        );
65
+    }
66
+
59
     @Override
67
     @Override
60
     public void mergeOptions(Options options) {
68
     public void mergeOptions(Options options) {
61
-        this.options = this.options.mergeWith(options);
69
+        super.mergeOptions(options);
62
         new SideMenuOptionsPresenter(getView()).present(this.options.sideMenuRootOptions);
70
         new SideMenuOptionsPresenter(getView()).present(this.options.sideMenuRootOptions);
63
-        this.options = this.options.copy().clearSideMenuOptions();
64
     }
71
     }
65
 
72
 
66
     public void setCenterController(ViewController centerController) {
73
     public void setCenterController(ViewController centerController) {

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

40
         this.animator = animator;
40
         this.animator = animator;
41
     }
41
     }
42
 
42
 
43
-    public void applyOptions(Options options) {
44
-        super.applyOptions(options);
45
-        getView().applyChildOptions(options);
46
-    }
47
-
48
     @Override
43
     @Override
49
     public void applyChildOptions(Options options, Component child) {
44
     public void applyChildOptions(Options options, Component child) {
50
         super.applyChildOptions(options, child);
45
         super.applyChildOptions(options, child);

+ 12
- 1
lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/ViewController.java View File

12
 
12
 
13
 import com.reactnativenavigation.parse.Options;
13
 import com.reactnativenavigation.parse.Options;
14
 import com.reactnativenavigation.presentation.FabOptionsPresenter;
14
 import com.reactnativenavigation.presentation.FabOptionsPresenter;
15
+import com.reactnativenavigation.presentation.OptionsPresenter;
15
 import com.reactnativenavigation.utils.CommandListener;
16
 import com.reactnativenavigation.utils.CommandListener;
16
 import com.reactnativenavigation.utils.StringUtils;
17
 import com.reactnativenavigation.utils.StringUtils;
17
 import com.reactnativenavigation.utils.Task;
18
 import com.reactnativenavigation.utils.Task;
42
     private boolean isShown;
43
     private boolean isShown;
43
     private boolean isDestroyed;
44
     private boolean isDestroyed;
44
     private ViewVisibilityListener viewVisibilityListener = new ViewVisibilityListenerAdapter();
45
     private ViewVisibilityListener viewVisibilityListener = new ViewVisibilityListenerAdapter();
46
+    private OptionsPresenter presenter;
45
     FabOptionsPresenter fabOptionsPresenter;
47
     FabOptionsPresenter fabOptionsPresenter;
46
 
48
 
47
     public ViewController(Activity activity, String id, Options initialOptions) {
49
     public ViewController(Activity activity, String id, Options initialOptions) {
48
         this.activity = activity;
50
         this.activity = activity;
49
         this.id = id;
51
         this.id = id;
52
+        presenter = new OptionsPresenter(activity);
50
         fabOptionsPresenter = new FabOptionsPresenter();
53
         fabOptionsPresenter = new FabOptionsPresenter();
51
         this.initialOptions = initialOptions;
54
         this.initialOptions = initialOptions;
52
         options = initialOptions.copy();
55
         options = initialOptions.copy();
67
         return false;
70
         return false;
68
     }
71
     }
69
 
72
 
70
-    public void applyOptions(Options options) {
73
+    @CallSuper
74
+    public void mergeOptions(Options options) {
75
+        this.options = this.options.mergeWith(options);
76
+        applyOptions(this.options);
77
+        this.options.clearOneTimeOptions();
78
+    }
71
 
79
 
80
+    @CallSuper
81
+    public void applyOptions(Options options) {
82
+        presenter.present(getView(), options);
72
     }
83
     }
73
 
84
 
74
     public Activity getActivity() {
85
     public Activity getActivity() {

+ 1
- 8
lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/bottomtabs/BottomTabsController.java View File

11
 import com.reactnativenavigation.parse.BottomTabOptions;
11
 import com.reactnativenavigation.parse.BottomTabOptions;
12
 import com.reactnativenavigation.parse.Options;
12
 import com.reactnativenavigation.parse.Options;
13
 import com.reactnativenavigation.presentation.BottomTabsOptionsPresenter;
13
 import com.reactnativenavigation.presentation.BottomTabsOptionsPresenter;
14
-import com.reactnativenavigation.presentation.NavigationOptionsListener;
15
 import com.reactnativenavigation.react.EventEmitter;
14
 import com.reactnativenavigation.react.EventEmitter;
16
 import com.reactnativenavigation.utils.CommandListener;
15
 import com.reactnativenavigation.utils.CommandListener;
17
 import com.reactnativenavigation.utils.ImageLoader;
16
 import com.reactnativenavigation.utils.ImageLoader;
28
 import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
27
 import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
29
 import static android.widget.RelativeLayout.ALIGN_PARENT_BOTTOM;
28
 import static android.widget.RelativeLayout.ALIGN_PARENT_BOTTOM;
30
 
29
 
31
-public class BottomTabsController extends ParentController implements AHBottomNavigation.OnTabSelectedListener, NavigationOptionsListener, TabSelector {
30
+public class BottomTabsController extends ParentController implements AHBottomNavigation.OnTabSelectedListener, TabSelector {
32
 
31
 
33
 	private BottomTabs bottomTabs;
32
 	private BottomTabs bottomTabs;
34
 	private List<ViewController> tabs = new ArrayList<>();
33
 	private List<ViewController> tabs = new ArrayList<>();
147
 		return tabs;
146
 		return tabs;
148
 	}
147
 	}
149
 
148
 
150
-	@Override
151
-	public void mergeOptions(Options options) {
152
-        this.options = this.options.mergeWith(options);
153
-        presenter.present(this.options);
154
-    }
155
-
156
     @Override
149
     @Override
157
     public void selectTab(final int newIndex) {
150
     public void selectTab(final int newIndex) {
158
         getView().removeView(getCurrentView());
151
         getView().removeView(getCurrentView());

+ 0
- 5
lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/externalcomponent/ExternalComponentViewController.java View File

21
         this.reactInstanceManager = reactInstanceManager;
21
         this.reactInstanceManager = reactInstanceManager;
22
     }
22
     }
23
 
23
 
24
-    @Override
25
-    public void applyOptions(Options options) {
26
-        getView().applyOptions(options);
27
-    }
28
-
29
     @Override
24
     @Override
30
     protected ExternalComponentLayout createView() {
25
     protected ExternalComponentLayout createView() {
31
         ExternalComponentLayout content = new ExternalComponentLayout(getActivity());
26
         ExternalComponentLayout content = new ExternalComponentLayout(getActivity());

+ 1
- 7
lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/toptabs/TopTabsController.java View File

5
 import android.view.View;
5
 import android.view.View;
6
 
6
 
7
 import com.reactnativenavigation.parse.Options;
7
 import com.reactnativenavigation.parse.Options;
8
-import com.reactnativenavigation.presentation.NavigationOptionsListener;
9
 import com.reactnativenavigation.utils.Task;
8
 import com.reactnativenavigation.utils.Task;
10
 import com.reactnativenavigation.viewcontrollers.ParentController;
9
 import com.reactnativenavigation.viewcontrollers.ParentController;
11
 import com.reactnativenavigation.viewcontrollers.ViewController;
10
 import com.reactnativenavigation.viewcontrollers.ViewController;
17
 import java.util.Collection;
16
 import java.util.Collection;
18
 import java.util.List;
17
 import java.util.List;
19
 
18
 
20
-public class TopTabsController extends ParentController<TopTabsViewPager> implements NavigationOptionsListener {
19
+public class TopTabsController extends ParentController<TopTabsViewPager> {
21
 
20
 
22
     private List<ViewController> tabs;
21
     private List<ViewController> tabs;
23
     private TopTabsLayoutCreator viewCreator;
22
     private TopTabsLayoutCreator viewCreator;
88
         );
87
         );
89
     }
88
     }
90
 
89
 
91
-    @Override
92
-    public void mergeOptions(Options options) {
93
-
94
-    }
95
-
96
     public void switchToTab(int index) {
90
     public void switchToTab(int index) {
97
         getView().switchToTab(index);
91
         getView().switchToTab(index);
98
     }
92
     }

+ 0
- 3
lib/android/app/src/main/java/com/reactnativenavigation/views/Component.java View File

1
 package com.reactnativenavigation.views;
1
 package com.reactnativenavigation.views;
2
 
2
 
3
-import com.reactnativenavigation.parse.Options;
4
 import com.reactnativenavigation.views.topbar.TopBar;
3
 import com.reactnativenavigation.views.topbar.TopBar;
5
 
4
 
6
 public interface Component {
5
 public interface Component {
7
-    void applyOptions(Options options);
8
-
9
     void drawBehindTopBar();
6
     void drawBehindTopBar();
10
 
7
 
11
     void drawBelowTopBar(TopBar topBar);
8
     void drawBelowTopBar(TopBar topBar);

+ 0
- 5
lib/android/app/src/main/java/com/reactnativenavigation/views/ComponentLayout.java View File

9
 
9
 
10
 import com.reactnativenavigation.interfaces.ScrollEventListener;
10
 import com.reactnativenavigation.interfaces.ScrollEventListener;
11
 import com.reactnativenavigation.parse.Options;
11
 import com.reactnativenavigation.parse.Options;
12
-import com.reactnativenavigation.presentation.ComponentOptionsPresenter;
13
 import com.reactnativenavigation.viewcontrollers.IReactView;
12
 import com.reactnativenavigation.viewcontrollers.IReactView;
14
 import com.reactnativenavigation.viewcontrollers.TopBarButtonController;
13
 import com.reactnativenavigation.viewcontrollers.TopBarButtonController;
15
 import com.reactnativenavigation.views.topbar.TopBar;
14
 import com.reactnativenavigation.views.topbar.TopBar;
22
 
21
 
23
     private IReactView reactView;
22
     private IReactView reactView;
24
     private final OverlayTouchDelegate touchDelegate;
23
     private final OverlayTouchDelegate touchDelegate;
25
-    private final ComponentOptionsPresenter optionsPresenter;
26
 
24
 
27
     public ComponentLayout(Context context, IReactView reactView) {
25
     public ComponentLayout(Context context, IReactView reactView) {
28
 		super(context);
26
 		super(context);
30
         addView(reactView.asView(), MATCH_PARENT, MATCH_PARENT);
28
         addView(reactView.asView(), MATCH_PARENT, MATCH_PARENT);
31
         setContentDescription("ComponentLayout");
29
         setContentDescription("ComponentLayout");
32
         touchDelegate = new OverlayTouchDelegate(reactView);
30
         touchDelegate = new OverlayTouchDelegate(reactView);
33
-        optionsPresenter = new ComponentOptionsPresenter(this);
34
     }
31
     }
35
 
32
 
36
     @Override
33
     @Override
58
 		reactView.sendComponentStop();
55
 		reactView.sendComponentStop();
59
 	}
56
 	}
60
 
57
 
61
-    @Override
62
     public void applyOptions(Options options) {
58
     public void applyOptions(Options options) {
63
-        optionsPresenter.present(options);
64
         touchDelegate.setInterceptTouchOutside(options.overlayOptions.interceptTouchOutside.isTrue());
59
         touchDelegate.setInterceptTouchOutside(options.overlayOptions.interceptTouchOutside.isTrue());
65
     }
60
     }
66
 
61
 

+ 0
- 7
lib/android/app/src/main/java/com/reactnativenavigation/views/ExternalComponentLayout.java View File

5
 import android.widget.FrameLayout;
5
 import android.widget.FrameLayout;
6
 import android.widget.RelativeLayout;
6
 import android.widget.RelativeLayout;
7
 
7
 
8
-import com.reactnativenavigation.parse.Options;
9
-import com.reactnativenavigation.presentation.ComponentOptionsPresenter;
10
 import com.reactnativenavigation.views.topbar.TopBar;
8
 import com.reactnativenavigation.views.topbar.TopBar;
11
 
9
 
12
 import static android.widget.RelativeLayout.BELOW;
10
 import static android.widget.RelativeLayout.BELOW;
18
         setContentDescription("ExternalComponentLayout");
16
         setContentDescription("ExternalComponentLayout");
19
     }
17
     }
20
 
18
 
21
-    @Override
22
-    public void applyOptions(Options options) {
23
-        new ComponentOptionsPresenter(this).present(options);
24
-    }
25
-
26
     @Override
19
     @Override
27
     public void drawBehindTopBar() {
20
     public void drawBehindTopBar() {
28
         if (getParent() instanceof RelativeLayout) {
21
         if (getParent() instanceof RelativeLayout) {

+ 3
- 3
lib/android/app/src/main/java/com/reactnativenavigation/views/StackLayout.java View File

5
 import android.widget.RelativeLayout;
5
 import android.widget.RelativeLayout;
6
 
6
 
7
 import com.reactnativenavigation.parse.Options;
7
 import com.reactnativenavigation.parse.Options;
8
-import com.reactnativenavigation.presentation.OptionsPresenter;
8
+import com.reactnativenavigation.presentation.StackOptionsPresenter;
9
 import com.reactnativenavigation.viewcontrollers.ReactViewCreator;
9
 import com.reactnativenavigation.viewcontrollers.ReactViewCreator;
10
 import com.reactnativenavigation.viewcontrollers.TopBarButtonController;
10
 import com.reactnativenavigation.viewcontrollers.TopBarButtonController;
11
 import com.reactnativenavigation.viewcontrollers.ViewController;
11
 import com.reactnativenavigation.viewcontrollers.ViewController;
19
 @SuppressLint("ViewConstructor")
19
 @SuppressLint("ViewConstructor")
20
 public class StackLayout extends RelativeLayout {
20
 public class StackLayout extends RelativeLayout {
21
     private String stackId;
21
     private String stackId;
22
-    private final OptionsPresenter optionsPresenter;
22
+    private final StackOptionsPresenter optionsPresenter;
23
 
23
 
24
     public StackLayout(Context context, ReactViewCreator topBarButtonCreator, TitleBarReactViewCreator titleBarReactViewCreator, TopBarBackgroundViewController topBarBackgroundViewController, TopBarController topBarController, TopBarButtonController.OnClickListener topBarButtonClickListener, String stackId) {
24
     public StackLayout(Context context, ReactViewCreator topBarButtonCreator, TitleBarReactViewCreator titleBarReactViewCreator, TopBarBackgroundViewController topBarBackgroundViewController, TopBarController topBarController, TopBarButtonController.OnClickListener topBarButtonClickListener, String stackId) {
25
         super(context);
25
         super(context);
26
         this.stackId = stackId;
26
         this.stackId = stackId;
27
         createLayout(topBarButtonCreator, titleBarReactViewCreator, topBarBackgroundViewController, topBarController, topBarButtonClickListener);
27
         createLayout(topBarButtonCreator, titleBarReactViewCreator, topBarBackgroundViewController, topBarController, topBarButtonClickListener);
28
-        optionsPresenter = new OptionsPresenter(topBarController.getView());
28
+        optionsPresenter = new StackOptionsPresenter(topBarController.getView());
29
         setContentDescription("StackLayout");
29
         setContentDescription("StackLayout");
30
     }
30
     }
31
 
31
 

+ 4
- 5
lib/android/app/src/main/java/com/reactnativenavigation/views/toptabs/TopTabsViewPager.java View File

41
         addOnPageChangeListener(adapter);
41
         addOnPageChangeListener(adapter);
42
     }
42
     }
43
 
43
 
44
-    @Override
45
-    public void applyOptions(Options options) {
46
-
47
-    }
48
-
49
     @Override
44
     @Override
50
     public void drawBehindTopBar() {
45
     public void drawBehindTopBar() {
51
         RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) getLayoutParams();
46
         RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) getLayoutParams();
83
         }
78
         }
84
         return false;
79
         return false;
85
     }
80
     }
81
+
82
+    public void applyOptions(Options options) {
83
+
84
+    }
86
 }
85
 }

+ 8
- 6
lib/android/app/src/test/java/com/reactnativenavigation/mocks/SimpleViewController.java View File

10
 import com.reactnativenavigation.interfaces.ScrollEventListener;
10
 import com.reactnativenavigation.interfaces.ScrollEventListener;
11
 import com.reactnativenavigation.parse.Options;
11
 import com.reactnativenavigation.parse.Options;
12
 import com.reactnativenavigation.viewcontrollers.ViewController;
12
 import com.reactnativenavigation.viewcontrollers.ViewController;
13
+import com.reactnativenavigation.views.Component;
13
 import com.reactnativenavigation.views.ReactComponent;
14
 import com.reactnativenavigation.views.ReactComponent;
14
 import com.reactnativenavigation.views.topbar.TopBar;
15
 import com.reactnativenavigation.views.topbar.TopBar;
15
 
16
 
37
         return "SimpleViewController " + getId();
38
         return "SimpleViewController " + getId();
38
     }
39
     }
39
 
40
 
40
-    public class SimpleView extends FrameLayout implements ReactComponent {
41
+    @Override
42
+    public void mergeOptions(Options options) {
43
+        applyOnParentController(parentController -> parentController.mergeChildOptions(options, (Component) view));
44
+        super.mergeOptions(options);
45
+    }
46
+
47
+    public static class SimpleView extends FrameLayout implements ReactComponent {
41
 
48
 
42
         public SimpleView(@NonNull Context context) {
49
         public SimpleView(@NonNull Context context) {
43
             super(context);
50
             super(context);
44
         }
51
         }
45
 
52
 
46
-        @Override
47
-        public void applyOptions(Options options) {
48
-
49
-        }
50
-
51
         @Override
53
         @Override
52
         public void drawBehindTopBar() {
54
         public void drawBehindTopBar() {
53
 
55
 

+ 0
- 2
lib/android/app/src/test/java/com/reactnativenavigation/parse/OptionsTest.java View File

91
         assertThat(result.topBar.hideOnScroll.get()).isEqualTo(TOP_BAR_HIDE_ON_SCROLL.get());
91
         assertThat(result.topBar.hideOnScroll.get()).isEqualTo(TOP_BAR_HIDE_ON_SCROLL.get());
92
         assertThat(result.bottomTabsOptions.animate.get()).isEqualTo(BOTTOM_TABS_ANIMATE.get());
92
         assertThat(result.bottomTabsOptions.animate.get()).isEqualTo(BOTTOM_TABS_ANIMATE.get());
93
         assertThat(result.bottomTabsOptions.visible.get()).isEqualTo(BOTTOM_TABS_VISIBLE.get());
93
         assertThat(result.bottomTabsOptions.visible.get()).isEqualTo(BOTTOM_TABS_VISIBLE.get());
94
-        assertThat(result.bottomTabsOptions.currentTabId.get()).isEqualTo(BOTTOM_TABS_CURRENT_TAB_ID);
95
-        assertThat(result.bottomTabsOptions.currentTabIndex.get()).isEqualTo(BOTTOM_TABS_CURRENT_TAB_INDEX.get());
96
         assertThat(result.fabOptions.id.get()).isEqualTo(FAB_ID);
94
         assertThat(result.fabOptions.id.get()).isEqualTo(FAB_ID);
97
         assertThat(result.fabOptions.backgroundColor.get()).isEqualTo(FAB_BACKGROUND_COLOR);
95
         assertThat(result.fabOptions.backgroundColor.get()).isEqualTo(FAB_BACKGROUND_COLOR);
98
         assertThat(result.fabOptions.clickColor.get()).isEqualTo(FAB_CLICK_COLOR);
96
         assertThat(result.fabOptions.clickColor.get()).isEqualTo(FAB_CLICK_COLOR);

+ 16
- 1
lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/BottomTabsControllerTest.java View File

53
 
53
 
54
     @Override
54
     @Override
55
     public void beforeEach() {
55
     public void beforeEach() {
56
-        super.beforeEach();
57
         activity = newActivity();
56
         activity = newActivity();
58
         eventEmitter = Mockito.mock(EventEmitter.class);
57
         eventEmitter = Mockito.mock(EventEmitter.class);
59
         uut = spy(new BottomTabsController(activity, eventEmitter, imageLoaderMock, "uut", new Options()));
58
         uut = spy(new BottomTabsController(activity, eventEmitter, imageLoaderMock, "uut", new Options()));
90
     public void setTabs_AddAllViews() {
89
     public void setTabs_AddAllViews() {
91
         List<ViewController> tabs = createTabs();
90
         List<ViewController> tabs = createTabs();
92
         uut.setTabs(tabs);
91
         uut.setTabs(tabs);
92
+        uut.onViewAppeared();
93
         assertThat(uut.getView().getChildCount()).isEqualTo(2);
93
         assertThat(uut.getView().getChildCount()).isEqualTo(2);
94
         assertThat(((ViewController) ((List) uut.getChildControllers()).get(0)).getView().getParent()).isNotNull();
94
         assertThat(((ViewController) ((List) uut.getChildControllers()).get(0)).getView().getParent()).isNotNull();
95
     }
95
     }
178
         verify(eventEmitter, times(0)).emitBottomTabSelected(any(Integer.class), any(Integer.class));
178
         verify(eventEmitter, times(0)).emitBottomTabSelected(any(Integer.class), any(Integer.class));
179
     }
179
     }
180
 
180
 
181
+    @Test
182
+    public void child_mergeOptions_currentTabIndex() {
183
+        List<ViewController> tabs = createTabs();
184
+        uut.setTabs(tabs);
185
+        uut.ensureViewIsCreated();
186
+
187
+        assertThat(uut.getSelectedIndex()).isZero();
188
+
189
+        Options options = new Options();
190
+        options.bottomTabsOptions.currentTabIndex = new Number(1);
191
+        child1.mergeOptions(options);
192
+
193
+        assertThat(uut.getSelectedIndex()).isOne();
194
+    }
195
+
181
     @Test
196
     @Test
182
     public void buttonPressInvokedOnCurrentTab() {
197
     public void buttonPressInvokedOnCurrentTab() {
183
         uut.setTabs(createTabs());
198
         uut.setTabs(createTabs());

+ 3
- 3
lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/OptionsMergingTest.java View File

15
 import com.reactnativenavigation.parse.params.Fraction;
15
 import com.reactnativenavigation.parse.params.Fraction;
16
 import com.reactnativenavigation.parse.params.Number;
16
 import com.reactnativenavigation.parse.params.Number;
17
 import com.reactnativenavigation.parse.params.Text;
17
 import com.reactnativenavigation.parse.params.Text;
18
-import com.reactnativenavigation.presentation.OptionsPresenter;
18
+import com.reactnativenavigation.presentation.StackOptionsPresenter;
19
 import com.reactnativenavigation.views.topbar.TopBar;
19
 import com.reactnativenavigation.views.topbar.TopBar;
20
 
20
 
21
 import org.json.JSONObject;
21
 import org.json.JSONObject;
35
 
35
 
36
 public class OptionsMergingTest extends BaseTest {
36
 public class OptionsMergingTest extends BaseTest {
37
 
37
 
38
-    private OptionsPresenter uut;
38
+    private StackOptionsPresenter uut;
39
     private TestComponentLayout child;
39
     private TestComponentLayout child;
40
     private Activity activity;
40
     private Activity activity;
41
     private TopBar topBar;
41
     private TopBar topBar;
44
     public void beforeEach() {
44
     public void beforeEach() {
45
         activity = spy(newActivity());
45
         activity = spy(newActivity());
46
         topBar = mockTopBar();
46
         topBar = mockTopBar();
47
-        uut = spy(new OptionsPresenter(topBar));
47
+        uut = spy(new StackOptionsPresenter(topBar));
48
         child = spy(new TestComponentLayout(activity, new TestReactView(activity)));
48
         child = spy(new TestComponentLayout(activity, new TestReactView(activity)));
49
     }
49
     }
50
 
50
 

+ 3
- 3
lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/SideMenuControllerTest.java View File

23
     }
23
     }
24
 
24
 
25
     @Test
25
     @Test
26
-    public void mergeOptions_openLeftSideMenu() throws Exception {
26
+    public void mergeOptions_openLeftSideMenu() {
27
         uut.setLeftController(new SimpleComponentViewController(activity, "left", new Options()));
27
         uut.setLeftController(new SimpleComponentViewController(activity, "left", new Options()));
28
 
28
 
29
         Options options = new Options();
29
         Options options = new Options();
34
     }
34
     }
35
 
35
 
36
     @Test
36
     @Test
37
-    public void mergeOptions_openRightSideMenu() throws Exception {
37
+    public void mergeOptions_openRightSideMenu() {
38
         uut.setRightController(new SimpleComponentViewController(activity, "right", new Options()));
38
         uut.setRightController(new SimpleComponentViewController(activity, "right", new Options()));
39
 
39
 
40
         Options options = new Options();
40
         Options options = new Options();
45
     }
45
     }
46
 
46
 
47
     @Test
47
     @Test
48
-    public void mergeOptions_optionsAreClearedAfterMerge() throws Exception {
48
+    public void mergeOptions_optionsAreClearedAfterMerge() {
49
         Options initialOptions = uut.options;
49
         Options initialOptions = uut.options;
50
         Options options = new Options();
50
         Options options = new Options();
51
         uut.mergeOptions(options);
51
         uut.mergeOptions(options);

+ 1
- 8
playground/src/screens/TextScreen.js View File

6
 const { Navigation } = require('react-native-navigation');
6
 const { Navigation } = require('react-native-navigation');
7
 const testIDs = require('../testIDs');
7
 const testIDs = require('../testIDs');
8
 
8
 
9
-let globalFirstComponentID;
10
-
11
 class TextScreen extends Component {
9
 class TextScreen extends Component {
12
   static get options() {
10
   static get options() {
13
     return {
11
     return {
20
     };
18
     };
21
   }
19
   }
22
 
20
 
23
-  constructor(props) {
24
-    super(props);
25
-    globalFirstComponentID = (props.text === 'This is tab 1') ? props.componentId : globalFirstComponentID;
26
-  }
27
-
28
   render() {
21
   render() {
29
     return (
22
     return (
30
       <View style={styles.root}>
23
       <View style={styles.root}>
79
   onClickSwitchToTabByComponentID() {
72
   onClickSwitchToTabByComponentID() {
80
     Navigation.mergeOptions(this.props.componentId, {
73
     Navigation.mergeOptions(this.props.componentId, {
81
       bottomTabs: {
74
       bottomTabs: {
82
-        currentTabId: globalFirstComponentID
75
+        currentTabId: 'TAB1_ID'
83
       }
76
       }
84
     });
77
     });
85
   }
78
   }

+ 1
- 0
playground/src/screens/WelcomeScreen.js View File

50
         children: [
50
         children: [
51
           {
51
           {
52
             stack: {
52
             stack: {
53
+              id: 'TAB1_ID',
53
               children: [
54
               children: [
54
                 {
55
                 {
55
                   component: {
56
                   component: {