1/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.car.cluster.sample;
18
19import android.content.Context;
20import android.util.AttributeSet;
21import android.util.Log;
22import android.view.View;
23import android.widget.FrameLayout;
24
25import java.util.ArrayList;
26import java.util.Arrays;
27import java.util.HashSet;
28import java.util.List;
29import java.util.Set;
30
31/**
32 * Panel that responsible of holding cards.
33 */
34public class CardPanel extends FrameLayout {
35    private final static String TAG = DebugUtil.getTag(CardPanel.class);
36
37    private final List<View> mOrderedChildren = new ArrayList<>(10);
38    private final Set<View> mViewsToBeRemoved = new HashSet<>();
39
40    public CardPanel(Context context) {
41        this(context, null);
42    }
43
44    public CardPanel(Context context, AttributeSet attrs) {
45        this(context, attrs, 0);
46    }
47
48    public CardPanel(Context context, AttributeSet attrs, int defStyleAttr) {
49        super(context, attrs, defStyleAttr);
50
51        setChildrenDrawingOrderEnabled(true);
52    }
53
54    @Override
55    public void addView(View child, int index) {
56        super.addView(child, index);
57        if (index < 0) {
58            mOrderedChildren.add(child);
59        } else {
60            mOrderedChildren.add(index, child);
61        }
62    }
63
64    @Override
65    public void removeView(View view) {
66        super.removeView(view);
67
68        mOrderedChildren.remove(view);
69        mViewsToBeRemoved.remove(view);
70    }
71
72    /**
73     * If we are removing view with animation, we do not want to treat this view as visible.
74     */
75    public void markViewToBeRemoved(View view) {
76        mViewsToBeRemoved.add(view);
77    }
78
79
80    public boolean childViewExists(View child) {
81        return indexOfChild(child) >= 0 && !mViewsToBeRemoved.contains(child);
82    }
83
84    /** Moves given child behind the top card */
85    public void moveChildBehindTheTop(View child) {
86        if (mOrderedChildren.size() <= 1) {
87            return;
88        }
89
90        int newIndex = mOrderedChildren.size() - 2;
91        int oldIndex = mOrderedChildren.indexOf(child);
92        if (oldIndex == -1) {
93            Log.e(TAG, "Child: " + child + " not found in "
94                    + Arrays.toString(mOrderedChildren.toArray()));
95            return;
96        }
97        if (newIndex == oldIndex) {
98            return;
99        }
100
101        // Swap children.
102        View tmpChild = mOrderedChildren.get(newIndex);
103        mOrderedChildren.set(newIndex, child);
104        mOrderedChildren.set(oldIndex, tmpChild);
105    }
106
107    public View getTopVisibleChild() {
108        for (int i = mOrderedChildren.size() - 1; i >= 0; i--) {
109            View child = mOrderedChildren.get(i);
110            if (child.getVisibility() == VISIBLE && !mViewsToBeRemoved.contains(child)) {
111                return child;
112            }
113        }
114        return null;
115    }
116
117    @SuppressWarnings("unchecked")
118    public <E> E getChildOrNull(Class<E> clazz) {
119        for (int i = 0; i < getChildCount(); i++) {
120            View child = getChildAt(i);
121            if (clazz.isInstance(child) && !mViewsToBeRemoved.contains(child)) {
122                return (E) child;
123            }
124        }
125        return null;
126    }
127
128    @SuppressWarnings("unchecked")
129    public <E> E getVisibleChildOrNull(Class<E> clazz) {
130        for (int i = 0; i < getChildCount(); i++) {
131            View child = getChildAt(i);
132            if (clazz.isInstance(child) && !mViewsToBeRemoved.contains(child)
133                    && child.getVisibility() == VISIBLE) {
134                return (E) child;
135            }
136        }
137        return null;
138    }
139
140    @Override
141    protected int getChildDrawingOrder(int childCount, int i) {
142        return indexOfChild(mOrderedChildren.get(i));
143    }
144}
145