1a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav/* 2a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav * Copyright (C) 2014 The Android Open Source Project 3a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav * 4a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav * Licensed under the Apache License, Version 2.0 (the "License"); 5a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav * you may not use this file except in compliance with the License. 6a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav * You may obtain a copy of the License at 7a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav * 8a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav * http://www.apache.org/licenses/LICENSE-2.0 9a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav * 10a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav * Unless required by applicable law or agreed to in writing, software 11a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav * distributed under the License is distributed on an "AS IS" BASIS, 12a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav * See the License for the specific language governing permissions and 14a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav * limitations under the License. 15a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav */ 16a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 17a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavpackage com.android.printspooler.widget; 18a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 19a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport android.content.Context; 20a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport android.content.res.TypedArray; 21a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport android.util.AttributeSet; 22a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport android.view.View; 23a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport android.view.ViewGroup; 24a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport com.android.printspooler.R; 25a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 26a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav/** 27a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav * This class is a layout manager for the print options. The options are 28a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav * arranged in a configurable number of columns and enough rows to fit all 29a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav * the options given the column count. 30a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav */ 31a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav@SuppressWarnings("unused") 32a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavpublic final class PrintOptionsLayout extends ViewGroup { 33a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 34525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov private int mColumnCount; 35a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 36a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav public PrintOptionsLayout(Context context, AttributeSet attrs) { 37a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav super(context, attrs); 38a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 39a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav TypedArray typedArray = context.obtainStyledAttributes(attrs, 40a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav R.styleable.PrintOptionsLayout); 41a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav mColumnCount = typedArray.getInteger(R.styleable.PrintOptionsLayout_columnCount, 0); 42a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav typedArray.recycle(); 43a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } 44a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 45525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov public void setColumnCount(int columnCount) { 46525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov if (mColumnCount != columnCount) { 47525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov mColumnCount = columnCount; 48525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov requestLayout(); 49525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 50525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov } 51525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov 52a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav @Override 53a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 54a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav final int widthMode = MeasureSpec.getMode(widthMeasureSpec); 55a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav final int widthSize = MeasureSpec.getSize(widthMeasureSpec); 56a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 57a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav final int columnWidth = (widthSize != 0) 58a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav ? (widthSize - mPaddingLeft - mPaddingRight) / mColumnCount : 0; 59a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 60a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav int width = 0; 61a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav int height = 0; 62a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav int childState = 0; 63a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 64a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav final int childCount = getChildCount(); 65a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav final int rowCount = childCount / mColumnCount + childCount % mColumnCount; 66a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 67a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav for (int row = 0; row < rowCount; row++) { 68a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav int rowWidth = 0; 69a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav int rowHeight = 0; 70a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 71a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav for (int col = 0; col < mColumnCount; col++) { 72a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav final int childIndex = row * mColumnCount + col; 73a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 74a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav if (childIndex >= childCount) { 75a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav break; 76a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } 77a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 78a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav View child = getChildAt(childIndex); 79a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 80a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav if (child.getVisibility() == GONE) { 81a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav continue; 82a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } 83a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 84a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav MarginLayoutParams childParams = (MarginLayoutParams) child.getLayoutParams(); 85a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 86a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav final int childWidthMeasureSpec; 87a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav if (columnWidth > 0) { 88a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav childWidthMeasureSpec = MeasureSpec.makeMeasureSpec( 89a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav columnWidth - childParams.getMarginStart() - childParams.getMarginEnd(), 90a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav MeasureSpec.EXACTLY); 91a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } else { 923ab1ec05491d5da8eea070889c03b6ea4f2af5bcSvetoslav childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec, 93a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav getPaddingStart() + getPaddingEnd() + width, childParams.width); 94a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } 95a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 96a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav final int childHeightMeasureSpec = getChildMeasureSpec(heightMeasureSpec, 97a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav getPaddingTop() + getPaddingBottom() + height, childParams.height); 98a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 99a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav child.measure(childWidthMeasureSpec, childHeightMeasureSpec); 100a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 101a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav childState = combineMeasuredStates(childState, child.getMeasuredState()); 102a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 103a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav rowWidth += child.getMeasuredWidth() + childParams.getMarginStart() 104a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav + childParams.getMarginEnd(); 105a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 106a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav rowHeight = Math.max(rowHeight, child.getMeasuredHeight() + childParams.topMargin 107a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav + childParams.bottomMargin); 108a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } 109a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 110a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav width = Math.max(width, rowWidth); 111a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav height += rowHeight; 112a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } 113a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 114a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav width += getPaddingStart() + getPaddingEnd(); 115a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav width = Math.max(width, getMinimumWidth()); 116a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 117a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav height += getPaddingTop() + getPaddingBottom(); 118a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav height = Math.max(height, getMinimumHeight()); 119a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 120a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav setMeasuredDimension(resolveSizeAndState(width, widthMeasureSpec, childState), 121a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav resolveSizeAndState(height, heightMeasureSpec, 122a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav childState << MEASURED_HEIGHT_STATE_SHIFT)); 123a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } 124a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 125a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav @Override 126a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav protected void onLayout(boolean changed, int l, int t, int r, int b) { 127a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav final int childCount = getChildCount(); 128a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav final int rowCount = childCount / mColumnCount + childCount % mColumnCount; 129a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 130a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav int cellStart = getPaddingStart(); 131a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav int cellTop = getPaddingTop(); 132a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 133a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav for (int row = 0; row < rowCount; row++) { 134a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav int rowHeight = 0; 135a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 136a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav for (int col = 0; col < mColumnCount; col++) { 137a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav final int childIndex = row * mColumnCount + col; 138a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 139a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav if (childIndex >= childCount) { 140a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav break; 141a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } 142a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 143a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav View child = getChildAt(childIndex); 144a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 145a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav if (child.getVisibility() == GONE) { 146a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav continue; 147a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } 148a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 149a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav MarginLayoutParams childParams = (MarginLayoutParams) child.getLayoutParams(); 150a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 151a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav final int childLeft = cellStart + childParams.getMarginStart(); 152a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav final int childTop = cellTop + childParams.topMargin; 153a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav final int childRight = childLeft + child.getMeasuredWidth(); 154a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav final int childBottom = childTop + child.getMeasuredHeight(); 155a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 156a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav child.layout(childLeft, childTop, childRight, childBottom); 157a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 158a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav cellStart = childRight + childParams.getMarginEnd(); 159a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 160a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav rowHeight = Math.max(rowHeight, child.getMeasuredHeight() 161a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav + childParams.topMargin + childParams.bottomMargin); 162a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } 163a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 164a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav cellStart = getPaddingStart(); 16538781bd2c2c61385651314098b4a615cb8e8efa1Svet Ganov cellTop += rowHeight; 166a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } 167a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } 168a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 169a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav @Override 170a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav public LayoutParams generateLayoutParams(AttributeSet attrs) { 171a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav return new ViewGroup.MarginLayoutParams(getContext(), attrs); 172a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } 173a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav} 174