package tk.wasdennnoch.androidn_ify.extracted.systemui.qs;
import android.content.Context;
import android.content.res.Configuration;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.TextView;
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.ConfigUtils;
import tk.wasdennnoch.androidn_ify.utils.ResourceUtils;
public class PagedTileLayout extends ViewPager implements QuickSettingsHooks.QSTileLayout {
private static final String TAG = "PagedTileLayout";
private final ArrayList<Object> mTiles = new ArrayList<>();
private final ArrayList<TilePage> mPages = new ArrayList<>();
private final Context mContext;
private final int mBottomMargin;
private PageIndicator mPageIndicator;
private int mNumPages;
private FrameLayout mDecorGroup;
private PageListener mPageListener;
private int mPosition;
private boolean mOffPage;
private TextView mEditBtn;
public boolean mFirstRowLarge = ConfigUtils.qs().large_first_row;
public PagedTileLayout(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
mBottomMargin = ResourceUtils.getInstance(context).getDimensionPixelSize(R.dimen.qs_edit_bottom_margin);
setClipChildren(false);
setClipToPadding(false);
setAdapter(mAdapter);
addOnPageChangeListener(new OnPageChangeListener() {
@Override
public void onPageSelected(int position) {
if (mPageIndicator == null) return;
if (mPageListener != null) {
mPageListener.onPageChanged(position == 0);
}
}
@Override
public void onPageScrolled(int position, float positionOffset,
int positionOffsetPixels) {
if (mPageIndicator == null) return;
setCurrentPage(position, positionOffset != 0);
mPageIndicator.setLocation(position + positionOffset);
if (mPageListener != null) {
mPageListener.onPageChanged(position == 0);
}
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
setCurrentItem(0);
addDecorView();
}
@Override
public void setCurrentItem(int item, boolean smoothScroll) {
super.setCurrentItem(item, smoothScroll);
}
protected Object getTileFromRecord(Object record) {
return XposedHelpers.getObjectField(record, "tile");
}
/**
* Sets individual pages to listening or not. If offPage it will set
* the next page after position to listening as well since we are in between
* pages.
*/
private void setCurrentPage(int position, boolean offPage) {
if (mPosition == position && mOffPage == offPage) return;
// Save the current state.
mPosition = position;
mOffPage = offPage;
}
@Override
public boolean hasOverlappingRendering() {
return false;
}
@Override
public int getOffsetTop(Object tile) {
final ViewGroup parent = (ViewGroup) ((View) XposedHelpers.getObjectField(tile, "tileView")).getParent();
if (parent == null) return 0;
return parent.getTop() + getTop();
}
@Override
public void addTile(Object tile) {
mTiles.add(tile);
postDistributeTiles();
}
@Override
public void removeTile(Object tile) {
if (mTiles.remove(tile)) {
postDistributeTiles();
}
}
public void setPageListener(PageListener listener) {
mPageListener = listener;
}
private void postDistributeTiles() {
removeCallbacks(mDistribute);
post(mDistribute);
}
public void removeAll() {
final int NP = mPages.size();
for (int i = 0; i < NP; i++) {
mPages.get(i).removeAllViews();
}
}
private void distributeTiles() {
XposedHook.logD(TAG, "Distributing tiles");
removeAll();
int index = 0;
final int NT = mTiles.size();
for (int i = 0; i < NT; i++) {
Object tile = mTiles.get(i);
if (mPages.get(index).isFull()) {
if (++index == mPages.size()) {
XposedHook.logD(TAG, "Adding page for "
+ XposedHelpers.getObjectField(tile, "tile").getClass().getSimpleName());
mPages.add(new TilePage(mContext, null));
}
}
XposedHook.logD(TAG, "Adding " + getTileFromRecord(tile).getClass().getSimpleName() + " to " + index);
mPages.get(index).addTile(tile);
}
if (mNumPages != index + 1) {
mNumPages = index + 1;
while (mPages.size() > mNumPages) {
mPages.remove(mPages.size() - 1);
}
XposedHook.logD(TAG, "Size: " + mNumPages);
mPageIndicator.setNumPages(mNumPages);
setAdapter(mAdapter);
mAdapter.notifyDataSetChanged();
setCurrentItem(0, false);
}
}
@Override
public boolean updateResources() {
boolean changed = mFirstRowLarge;
for (int i = 0; i < mPages.size(); i++) {
changed |= mPages.get(i).updateResources();
}
if (mFirstRowLarge)
mPages.get(0).setFirstRowLarge(mContext.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT);
if (changed) {
distributeTiles();
}
return changed;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// The ViewPager likes to eat all of the space, instead force it to wrap to the max height
// of the pages.
int maxHeight = 0;
final int N = getChildCount();
for (int i = 0; i < N; i++) {
int height = getChildAt(i).getMeasuredHeight();
if (height > maxHeight) {
maxHeight = height;
}
}
setMeasuredDimension(getMeasuredWidth(), maxHeight +
(mNumPages > 1 ? mDecorGroup.getMeasuredHeight() : mBottomMargin));
}
private final Runnable mDistribute = new Runnable() {
@Override
public void run() {
distributeTiles();
}
};
public int getColumnCount() {
if (mPages.size() == 0) return 0;
return mPages.get(0).mColumns;
}
public void setColumnCount(int columns) {
// Use module settings when using default column count,
// override count otherwise (ROM settings)
if (columns == 3) return;
XposedHook.logD(TAG, "Overwriting column count to " + columns);
for (TilePage p : mPages)
p.setColumns(columns);
}
public int getRowCount() {
if (mPages.size() == 0) return 0;
return mPages.get(0).mMaxRows;
}
public TilePage getFirstPage() {
return mPages.get(0);
}
static class TilePage extends TileLayout {
private int mMaxRows = 3;
public TilePage(Context context, AttributeSet attrs) {
super(context, attrs);
updateResources();
setClipChildren(false);
setClipToPadding(false);
}
@Override
public boolean updateResources() {
final int rows = getRows();
boolean changed = rows != mMaxRows;
if (changed) {
mMaxRows = rows;
requestLayout();
}
return super.updateResources() || changed;
}
private int getRows() {
if (isPortrait()) {
// Always have 3 rows in portrait.
return 3;
}
return Math.max(1, ResourceUtils.getInstance(mContext).getResources().getInteger(R.integer.quick_settings_num_rows));
}
private boolean isPortrait() {
return getContext().getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;
}
public void setMaxRows(int maxRows) {
mMaxRows = maxRows;
}
public boolean isFull() {
return !(ConfigUtils.qs().disable_qs_paging && isPortrait()) && mRecords.size() >= getMaxTiles();
}
public int getMaxTiles() {
int max = mColumns * mMaxRows;
if (mFirstRowLarge)
max += 2 - mColumns;
return max;
}
}
private final PagerAdapter mAdapter = new PagerAdapter() {
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
XposedHook.logD(TAG, "Destantiating " + position);
container.removeView((View) object);
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
XposedHook.logD(TAG, "Instantiating " + position);
ViewGroup view = mPages.get(position);
container.addView(view);
return view;
}
@Override
public int getCount() {
return mNumPages;
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
};
public interface PageListener {
void onPageChanged(boolean isFirst);
}
private void addDecorView() {
ResourceUtils res = ResourceUtils.getInstance(mContext);
ViewPager.LayoutParams decorLayoutLp = new LayoutParams();
decorLayoutLp.width = ViewGroup.LayoutParams.MATCH_PARENT;
decorLayoutLp.height = res.getDimensionPixelSize(R.dimen.qs_panel_decor_height);
decorLayoutLp.gravity = Gravity.BOTTOM;
decorLayoutLp.isDecor = true;
mDecorGroup = new FrameLayout(mContext);
mDecorGroup.setLayoutParams(decorLayoutLp);
FrameLayout.LayoutParams pageIndicatorLp = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
pageIndicatorLp.gravity = Gravity.CENTER;
mPageIndicator = new PageIndicator(mContext);
mPageIndicator.setLayoutParams(pageIndicatorLp);
mDecorGroup.addView(mPageIndicator);
addView(mDecorGroup);
mPages.add(new TilePage(mContext, null));
}
}