package tk.wasdennnoch.androidn_ify.extracted.systemui.qs; import android.content.Context; import android.content.res.Configuration; import android.content.res.Resources; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; import java.util.ArrayList; import de.robv.android.xposed.XposedHelpers; import tk.wasdennnoch.androidn_ify.R; import tk.wasdennnoch.androidn_ify.XposedHook; import tk.wasdennnoch.androidn_ify.systemui.qs.QuickSettingsHooks; import tk.wasdennnoch.androidn_ify.utils.ResourceUtils; public class TileLayout extends ViewGroup implements QuickSettingsHooks.QSTileLayout { private static final String TAG = "TileLayout"; protected final Context mContext; protected int mColumns; protected int mCellWidth; protected int mCellHeight; protected int mLargeCellWidth; protected int mCellMargin; protected boolean mFirstRowLarge = false; protected final ArrayList<Object> mRecords = new ArrayList<>(); private int mCellMarginTop; private int mPortraitColumns = 3; public TileLayout(Context context) { this(context, null); } public TileLayout(Context context, AttributeSet attrs) { super(context, attrs); mContext = context; setClipChildren(false); setClipToPadding(false); setFocusableInTouchMode(true); updateResources(); } protected Object getTileFromRecord(Object record) { return XposedHelpers.getObjectField(record, "tile"); } protected ViewGroup getTileViewFromRecord(Object record) { return (ViewGroup) XposedHelpers.getObjectField(record, "tileView"); } @Override public int getOffsetTop(Object tile) { return getTop(); } public void addTile(Object tile) { mRecords.add(tile); View tileView = getTileViewFromRecord(tile); if (tileView.getParent() != null) ((ViewGroup) tileView.getParent()).removeView(tileView); addView(tileView); } @Override public void removeTile(Object tile) { mRecords.remove(tile); removeView(getTileViewFromRecord(tile)); } public void removeAllViews() { mRecords.clear(); super.removeAllViews(); } public boolean updateResources() { Resources res = ResourceUtils.getInstance(mContext).getResources(); int columns = Math.max(1, res.getInteger(R.integer.quick_settings_num_columns)); if (mContext.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) { columns = mPortraitColumns; } mLargeCellWidth = res.getDimensionPixelSize(R.dimen.qs_dual_tile_width); mCellHeight = res.getDimensionPixelSize(R.dimen.qs_tile_height); mCellMargin = res.getDimensionPixelSize(R.dimen.qs_tile_margin); mCellMarginTop = res.getDimensionPixelSize(R.dimen.qs_tile_margin_top); if (mColumns != columns) { mColumns = columns; requestLayout(); return true; } return false; } public void setColumns(int columns) { if (mPortraitColumns != columns) { mPortraitColumns = columns; updateResources(); } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { final int numTiles = mRecords.size(); final int width = MeasureSpec.getSize(widthMeasureSpec); final int rows = (numTiles + mColumns - 1) / mColumns; mCellWidth = (width - (mCellMargin * (mColumns + 1))) / mColumns; int row = 0; int column = 0; for (Object record : mRecords) { View tileView = getTileViewFromRecord(record); if (tileView.getVisibility() != VISIBLE) continue; if (column == getColumns(row)) { row++; column = 0; } setDual(record); try { tileView.measure(exactly(getCellWidth(row)), exactly(mCellHeight)); } catch (Throwable t) { XposedHook.logE(TAG, "Fatal Error measuring " + tileView.getClass().getSimpleName() + " for " + getTileFromRecord(record).getClass().getSimpleName(), t); } column++; } setMeasuredDimension(width, (mCellHeight + mCellMargin) * rows + (mCellMarginTop - mCellMargin)); } private void setDual(Object record) { View tileView = getTileViewFromRecord(record); try { XposedHelpers.callMethod(tileView, "setDual", new Class[]{boolean.class}, false); } catch (Throwable t) { // CM13 try { Object tile = getTileFromRecord(record); XposedHelpers.callMethod(tileView, "setDual", new Class[]{boolean.class, boolean.class}, false, XposedHelpers.callMethod(tile, "hasDualTargetsDetails")); } catch (Throwable ignore) { // Other ROMs } } } private boolean isDual(int row) { return mFirstRowLarge && row == 0; } private int getColumns(int row) { return isDual(row) ? 2 : mColumns; } private static int exactly(int size) { return MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { int row = 0; int column = 0; for (int i = 0; i < mRecords.size(); i++) { Object record = mRecords.get(i); View tileView = getTileViewFromRecord(record); if (tileView.getVisibility() != VISIBLE) continue; if (column == getColumns(row)) { row++; column = 0; } int left = getColumnStart(row, column); final int top = getRowTop(row); int right; right = left + getCellWidth(row); tileView.layout(left, top, right, top + tileView.getMeasuredHeight()); column++; } } private int getCellWidth(int row) { return (mFirstRowLarge && row == 0) ? mLargeCellWidth : mCellWidth; } private int getRowTop(int row) { return row * (mCellHeight + mCellMargin) + mCellMarginTop; } private int getColumnStart(int row, int column) { if (mFirstRowLarge && row == 0) { return column * mLargeCellWidth + (column + 1) * (getWidth() - mLargeCellWidth * 2) / (3); } else return column * (mCellWidth + mCellMargin) + mCellMargin; } public void setFirstRowLarge(boolean firstRowLarge) { mFirstRowLarge = firstRowLarge; requestLayout(); } }