package io.nextop.rx;
import android.annotation.SuppressLint;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewParent;
import android.widget.FrameLayout;
import rx.Observable;
import rx.Subscription;
import javax.annotation.Nullable;
// connects to the view lifecycle (attached to window, detached from window)
public final class RxViewGroup extends FrameLayout implements RxLifecycleBinder {
public static final Object TAG = new Object();
private final RxLifecycleBinder.Lifted liftedRxLifecycleBinder = new RxLifecycleBinder.Lifted();
public RxViewGroup(Context context) {
super(context);
init();
}
public RxViewGroup(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public RxViewGroup(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
@SuppressLint("NewApi")
public RxViewGroup(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init();
}
private void init() {
setTag(TAG);
}
@Override
public void reset() {
liftedRxLifecycleBinder.reset();
}
@Override
public boolean reset(Object id) {
return liftedRxLifecycleBinder.reset(id);
}
@Override
public <T> Observable<T> bind(Observable<T> source) {
return liftedRxLifecycleBinder.bind(source);
}
@Override
public void bind(Subscription sub) {
liftedRxLifecycleBinder.bind(sub);
}
@Override
public void unsubscribe() {
liftedRxLifecycleBinder.unsubscribe();
}
@Override
public boolean isUnsubscribed() {
return liftedRxLifecycleBinder.isUnsubscribed();
}
public void onDispose() {
liftedRxLifecycleBinder.close();
}
public void cascadeDispose(@Nullable RxLifecycleBinder parent) {
liftedRxLifecycleBinder.cascadeUnsubscribe(parent);
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
evalBinder();
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
evalBinder();
}
@Override
protected void onWindowVisibilityChanged(int visibility) {
super.onWindowVisibilityChanged(visibility);
evalBinder();
}
@Override
protected void onVisibilityChanged(View changedView, int visibility) {
super.onVisibilityChanged(changedView, visibility);
evalBinder();
}
/** calls either #connect or #disconnect on the binder,
* depending on the view state. Call this after a change to the view state. */
private void evalBinder() {
if (liftedRxLifecycleBinder.isClosed()) {
// abort; already done
return;
}
boolean connect;
if (View.VISIBLE == getWindowVisibility()) {
if (View.VISIBLE == getVisibility()) {
boolean visible = true;
for (ViewParent p = getParent(); visible && p instanceof View; p = p.getParent()) {
visible &= View.VISIBLE == ((View) p).getVisibility();
}
connect = visible;
} else {
connect = false;
}
} else {
connect = false;
}
if (connect) {
liftedRxLifecycleBinder.connect(this);
} else {
liftedRxLifecycleBinder.disconnect();
}
}
}