Home | History | Annotate | Download | only in widget
      1 /*
      2  * Copyright (C) 2014 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 
     17 package com.android.printspooler.widget;
     18 
     19 import android.content.Context;
     20 import android.content.res.TypedArray;
     21 import android.util.AttributeSet;
     22 import android.view.View;
     23 import android.view.ViewGroup;
     24 
     25 import com.android.printspooler.R;
     26 
     27 /**
     28  * This class is a layout manager for the print options. The options are
     29  * arranged in a configurable number of columns and enough rows to fit all
     30  * the options given the column count.
     31  */
     32 @SuppressWarnings("unused")
     33 public final class PrintOptionsLayout extends ViewGroup {
     34 
     35     private int mColumnCount;
     36 
     37     public PrintOptionsLayout(Context context, AttributeSet attrs) {
     38         super(context, attrs);
     39 
     40         TypedArray typedArray = context.obtainStyledAttributes(attrs,
     41                 R.styleable.PrintOptionsLayout);
     42         mColumnCount = typedArray.getInteger(R.styleable.PrintOptionsLayout_columnCount, 0);
     43         typedArray.recycle();
     44     }
     45 
     46     public void setColumnCount(int columnCount) {
     47         if (mColumnCount != columnCount) {
     48             mColumnCount = columnCount;
     49             requestLayout();
     50         }
     51     }
     52 
     53     @Override
     54     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
     55         final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
     56         final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
     57 
     58         final int columnWidth = (widthSize != 0)
     59                 ? (widthSize - mPaddingLeft - mPaddingRight) / mColumnCount : 0;
     60 
     61         int width = 0;
     62         int height = 0;
     63         int childState = 0;
     64 
     65         final int childCount = getChildCount();
     66         final int rowCount = childCount / mColumnCount + childCount % mColumnCount;
     67 
     68         for (int row = 0; row < rowCount; row++) {
     69             int rowWidth = 0;
     70             int rowHeight = 0;
     71 
     72             for (int col = 0; col < mColumnCount; col++) {
     73                 final int childIndex = row * mColumnCount + col;
     74 
     75                 if (childIndex >= childCount) {
     76                     break;
     77                 }
     78 
     79                 View child = getChildAt(childIndex);
     80 
     81                 if (child.getVisibility() == GONE) {
     82                     continue;
     83                 }
     84 
     85                 MarginLayoutParams childParams = (MarginLayoutParams) child.getLayoutParams();
     86 
     87                 final int childWidthMeasureSpec;
     88                 if (columnWidth > 0) {
     89                     childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(
     90                             columnWidth - childParams.getMarginStart() - childParams.getMarginEnd(),
     91                             MeasureSpec.EXACTLY);
     92                 } else {
     93                     childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec,
     94                             getPaddingStart() + getPaddingEnd() + width, childParams.width);
     95                 }
     96 
     97                 final int childHeightMeasureSpec = getChildMeasureSpec(heightMeasureSpec,
     98                         getPaddingTop() + getPaddingBottom() + height, childParams.height);
     99 
    100                 child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
    101 
    102                 childState = combineMeasuredStates(childState, child.getMeasuredState());
    103 
    104                 rowWidth += child.getMeasuredWidth() + childParams.getMarginStart()
    105                         + childParams.getMarginEnd();
    106 
    107                 rowHeight = Math.max(rowHeight, child.getMeasuredHeight() + childParams.topMargin
    108                         + childParams.bottomMargin);
    109             }
    110 
    111             width = Math.max(width, rowWidth);
    112             height += rowHeight;
    113         }
    114 
    115         width += getPaddingStart() + getPaddingEnd();
    116         width = Math.max(width, getMinimumWidth());
    117 
    118         height += getPaddingTop() + getPaddingBottom();
    119         height = Math.max(height, getMinimumHeight());
    120 
    121         setMeasuredDimension(resolveSizeAndState(width, widthMeasureSpec, childState),
    122                 resolveSizeAndState(height, heightMeasureSpec,
    123                         childState << MEASURED_HEIGHT_STATE_SHIFT));
    124     }
    125 
    126     @Override
    127     protected void onLayout(boolean changed, int l, int t, int r, int b) {
    128         final int childCount = getChildCount();
    129         final int rowCount = childCount / mColumnCount + childCount % mColumnCount;
    130         final boolean isLayoutRtl = isLayoutRtl();
    131 
    132         int cellStart = getPaddingStart();
    133         int cellTop = getPaddingTop();
    134 
    135         for (int row = 0; row < rowCount; row++) {
    136             int rowHeight = 0;
    137 
    138             for (int col = 0; col < mColumnCount; col++) {
    139                 final int childIndex;
    140                 if (isLayoutRtl) {
    141                     // if RTL, layout the right most child first
    142                     childIndex = row * mColumnCount + (mColumnCount - col - 1);
    143                 } else {
    144                     childIndex = row * mColumnCount + col;
    145                 }
    146 
    147                 if (childIndex >= childCount) {
    148                     break;
    149                 }
    150 
    151                 View child = getChildAt(childIndex);
    152 
    153                 if (child.getVisibility() == GONE) {
    154                     continue;
    155                 }
    156 
    157                 MarginLayoutParams childParams = (MarginLayoutParams) child.getLayoutParams();
    158 
    159                 final int childStart = cellStart + childParams.getMarginStart();
    160                 final int childTop = cellTop + childParams.topMargin;
    161                 final int childEnd = childStart + child.getMeasuredWidth();
    162                 final int childBottom = childTop + child.getMeasuredHeight();
    163 
    164                 child.layout(childStart, childTop, childEnd, childBottom);
    165 
    166                 cellStart = childEnd + childParams.getMarginEnd();
    167 
    168                 rowHeight = Math.max(rowHeight, child.getMeasuredHeight()
    169                         + childParams.topMargin + childParams.bottomMargin);
    170             }
    171 
    172             cellStart = getPaddingStart();
    173             cellTop += rowHeight;
    174         }
    175     }
    176 
    177     @Override
    178     public LayoutParams generateLayoutParams(AttributeSet attrs) {
    179         return new ViewGroup.MarginLayoutParams(getContext(), attrs);
    180     }
    181 }
    182