1/*
2 * Copyright (C) 2013 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 android.support.v7.internal.widget;
18
19import android.content.Context;
20import android.content.res.TypedArray;
21import android.graphics.Canvas;
22import android.graphics.drawable.Drawable;
23import android.support.v7.appcompat.R;
24import android.util.AttributeSet;
25import android.view.View;
26import android.widget.LinearLayout;
27
28/**
29 * @hide
30 */
31public class LinearLayoutICS extends LinearLayout {
32
33    private static final int SHOW_DIVIDER_NONE = 0;
34    private static final int SHOW_DIVIDER_BEGINNING = 1;
35    private static final int SHOW_DIVIDER_MIDDLE = 2;
36    private static final int SHOW_DIVIDER_END = 4;
37
38    private final Drawable mDivider;
39    private final int mDividerWidth, mDividerHeight;
40    private final int mShowDividers;
41    private final int mDividerPadding;
42
43    public LinearLayoutICS(Context context, AttributeSet attrs) {
44        super(context, attrs);
45
46        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.LinearLayoutICS);
47
48        mDivider = a.getDrawable(R.styleable.LinearLayoutICS_divider);
49        if (mDivider != null) {
50            mDividerWidth = mDivider.getIntrinsicWidth();
51            mDividerHeight = mDivider.getIntrinsicHeight();
52        } else {
53            mDividerHeight = mDividerWidth = 0;
54        }
55
56        mShowDividers = a.getInt(R.styleable.LinearLayoutICS_showDividers, SHOW_DIVIDER_NONE);
57        mDividerPadding = a.getDimensionPixelSize(R.styleable.LinearLayoutICS_dividerPadding, 0);
58
59        a.recycle();
60
61        setWillNotDraw(mDivider == null);
62    }
63
64    public int getSupportDividerWidth() {
65        return mDividerWidth;
66    }
67
68    @Override
69    protected void onDraw(Canvas canvas) {
70        if (mDivider == null) {
71            return;
72        }
73
74        if (getOrientation() == VERTICAL) {
75            drawSupportDividersVertical(canvas);
76        } else {
77            drawSupportDividersHorizontal(canvas);
78        }
79    }
80
81    @Override
82    protected void measureChildWithMargins(View child, int parentWidthMeasureSpec, int widthUsed,
83            int parentHeightMeasureSpec, int heightUsed) {
84
85        if (mDivider != null) {
86            final int childIndex = indexOfChild(child);
87            final int count = getChildCount();
88            final LayoutParams params = (LayoutParams) child.getLayoutParams();
89
90            // To display the dividers in-between the child views, we modify their margins
91            // to create space.
92            if (getOrientation() == VERTICAL) {
93                if (hasSupportDividerBeforeChildAt(childIndex)) {
94                    params.topMargin = mDividerHeight;
95                } else if (childIndex == count - 1 && hasSupportDividerBeforeChildAt(count)) {
96                    params.bottomMargin = mDividerHeight;
97                }
98            } else {
99                if (hasSupportDividerBeforeChildAt(childIndex)) {
100                    params.leftMargin = mDividerWidth;
101                } else if (childIndex == count - 1 && hasSupportDividerBeforeChildAt(count)) {
102                    params.rightMargin = mDividerWidth;
103                }
104            }
105        }
106
107        super.measureChildWithMargins(child, parentWidthMeasureSpec, widthUsed,
108                parentHeightMeasureSpec, heightUsed);
109    }
110
111    void drawSupportDividersVertical(Canvas canvas) {
112        final int count = getChildCount();
113        for (int i = 0; i < count; i++) {
114            final View child = getChildAt(i);
115            if (child != null && child.getVisibility() != GONE &&
116                    hasSupportDividerBeforeChildAt(i)) {
117                final LayoutParams lp = (LayoutParams) child.getLayoutParams();
118                drawSupportHorizontalDivider(canvas, child.getTop() - lp.topMargin);
119            }
120        }
121
122        if (hasSupportDividerBeforeChildAt(count)) {
123            final View child = getChildAt(count - 1);
124            int bottom = 0;
125            if (child == null) {
126                bottom = getHeight() - getPaddingBottom() - mDividerHeight;
127            } else {
128                bottom = child.getBottom();
129            }
130            drawSupportHorizontalDivider(canvas, bottom);
131        }
132    }
133
134    void drawSupportDividersHorizontal(Canvas canvas) {
135        final int count = getChildCount();
136        for (int i = 0; i < count; i++) {
137            final View child = getChildAt(i);
138            if (child != null && child.getVisibility() != GONE &&
139                    hasSupportDividerBeforeChildAt(i)) {
140                final LayoutParams lp = (LayoutParams) child.getLayoutParams();
141                drawSupportVerticalDivider(canvas, child.getLeft() - lp.leftMargin);
142            }
143        }
144
145        if (hasSupportDividerBeforeChildAt(count)) {
146            final View child = getChildAt(count - 1);
147            int right = 0;
148            if (child == null) {
149                right = getWidth() - getPaddingRight() - mDividerWidth;
150            } else {
151                right = child.getRight();
152            }
153            drawSupportVerticalDivider(canvas, right);
154        }
155    }
156
157    void drawSupportHorizontalDivider(Canvas canvas, int top) {
158        mDivider.setBounds(getPaddingLeft() + mDividerPadding, top,
159                getWidth() - getPaddingRight() - mDividerPadding, top + mDividerHeight);
160        mDivider.draw(canvas);
161    }
162
163    void drawSupportVerticalDivider(Canvas canvas, int left) {
164        mDivider.setBounds(left, getPaddingTop() + mDividerPadding,
165                left + mDividerWidth, getHeight() - getPaddingBottom() - mDividerPadding);
166        mDivider.draw(canvas);
167    }
168
169    /**
170     * Determines where to position dividers between children.
171     *
172     * @param childIndex Index of child to check for preceding divider
173     * @return true if there should be a divider before the child at childIndex
174     */
175    protected boolean hasSupportDividerBeforeChildAt(int childIndex) {
176        if (childIndex == 0) {
177            return (mShowDividers & SHOW_DIVIDER_BEGINNING) != 0;
178        } else if (childIndex == getChildCount()) {
179            return (mShowDividers & SHOW_DIVIDER_END) != 0;
180        } else if ((mShowDividers & SHOW_DIVIDER_MIDDLE) != 0) {
181            boolean hasVisibleViewBefore = false;
182            for (int i = childIndex - 1; i >= 0; i--) {
183                if (getChildAt(i).getVisibility() != GONE) {
184                    hasVisibleViewBefore = true;
185                    break;
186                }
187            }
188            return hasVisibleViewBefore;
189        }
190        return false;
191    }
192
193}
194