package tk.wasdennnoch.androidn_ify.extracted.systemui.qs;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.Space;
import java.util.ArrayList;
import java.util.List;
import de.robv.android.xposed.XposedHelpers;
import tk.wasdennnoch.androidn_ify.R;
import tk.wasdennnoch.androidn_ify.XposedHook;
import tk.wasdennnoch.androidn_ify.misc.SafeOnClickListener;
import tk.wasdennnoch.androidn_ify.misc.SafeOnLongClickListener;
import tk.wasdennnoch.androidn_ify.systemui.notifications.StatusBarHeaderHooks;
import tk.wasdennnoch.androidn_ify.systemui.qs.tiles.BatteryTile;
import tk.wasdennnoch.androidn_ify.utils.ConfigUtils;
import tk.wasdennnoch.androidn_ify.utils.ResourceUtils;
import static tk.wasdennnoch.androidn_ify.XposedHook.PACKAGE_SYSTEMUI;
import static tk.wasdennnoch.androidn_ify.systemui.qs.QSTileHostHooks.KEY_QUICKQS_TILEVIEW;
public class QuickQSPanel extends LinearLayout {
private static final String TAG = "QuickQSPanel";
private final int mIconSizePx;
private final int mQuickTilePadding;
private final int mMaxTiles;
private final HeaderTileLayout mTileLayout;
private final ResourceUtils mRes;
protected final ArrayList<Object> mRecords = new ArrayList<>();
private final ArrayList<View> mIconViews = new ArrayList<>();
private final boolean mShowPercent;
public QuickQSPanel(Context context) {
super(context);
ConfigUtils config = ConfigUtils.getInstance();
Resources res = context.getResources();
mIconSizePx = res.getDimensionPixelSize(res.getIdentifier("qs_tile_icon_size", "dimen", PACKAGE_SYSTEMUI));
mRes = ResourceUtils.getInstance(context);
mQuickTilePadding = mRes.getDimensionPixelSize(R.dimen.qs_quick_tile_padding);
mMaxTiles = config.qs.qs_tiles_count;
mShowPercent = config.qs.battery_tile_show_percentage;
setOrientation(VERTICAL);
int m = mRes.getDimensionPixelSize(R.dimen.qs_quick_panel_margin_horizontal);
setPadding(m, mRes.getDimensionPixelSize(R.dimen.qs_quick_panel_padding_top), m, mRes.getDimensionPixelSize(R.dimen.qs_quick_panel_padding_bottom));
mTileLayout = new HeaderTileLayout(context);
addView(mTileLayout);
}
public void setTiles(ArrayList<Object> tileRecords) {
if (tileRecords == null || tileRecords.size() == 0) {
XposedHook.logW(TAG, "setTiles: Empty tileRecord list! (null: " + (tileRecords == null) + ")");
return;
}
XposedHook.logD(TAG, "setTiles: Tile record count: " + tileRecords.size());
mTileLayout.removeTiles();
mRecords.clear();
mIconViews.clear();
for (int i = 0; i < tileRecords.size(); i++) {
Object tilerecord = tileRecords.get(i);
mRecords.add(tilerecord);
if (i < mMaxTiles)
mTileLayout.addTile(tilerecord);
}
if (StatusBarHeaderHooks.mQsAnimator == null)
StatusBarHeaderHooks.createQsAnimator();
StatusBarHeaderHooks.postSetupAnimators();
}
public void handleStateChanged(Object qsTile, Object state) {
ViewGroup tileView = (ViewGroup) XposedHelpers.getAdditionalInstanceField(qsTile, KEY_QUICKQS_TILEVIEW);
if (tileView != null) {
XposedHelpers.callMethod(tileView, "onStateChanged", state);
}
}
public List<Object> getRecords() {
return mRecords;
}
public View getTileView(int i) {
return mIconViews.get(i);
}
private class HeaderTileLayout extends LinearLayout {
public HeaderTileLayout(Context context) {
super(context);
setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
setOrientation(HORIZONTAL);
setGravity(Gravity.CENTER_VERTICAL);
setClipChildren(false);
setClipToPadding(false);
}
public void addTile(Object tilerecord) {
final Object tile = XposedHelpers.getObjectField(tilerecord, "tile");
XposedHook.logD(TAG, "addTile: original tileView class: " +
XposedHelpers.getObjectField(tilerecord, "tileView").getClass().getSimpleName() +
" for tile " + tile.getClass().getSimpleName());
ViewGroup tileView = (ViewGroup) XposedHelpers.callMethod(tile, "createTileView", getContext());
XposedHelpers.setAdditionalInstanceField(tileView, "headerTileRowItem", true);
XposedHelpers.setAdditionalInstanceField(tileView, "headerTileRowType", tile.getClass().getSimpleName());
View.OnClickListener click = new View.OnClickListener() {
@Override
public void onClick(View v) {
if (getTileVisibility(tile)) {
try {
XposedHelpers.callMethod(tile, "click");
} catch (Throwable t) {
try { // PA
XposedHelpers.callMethod(tile, "click", false);
} catch (Throwable ignore) {
}
}
}
}
};
View.OnClickListener clickSecondary = new SafeOnClickListener() {
@Override
public void onClickSafe(View v) {
if (getTileVisibility(tile)) {
XposedHelpers.callMethod(tile, "secondaryClick");
}
}
};
View.OnLongClickListener longClick = new SafeOnLongClickListener() {
@Override
public boolean onLongClickSafe(View v) {
if (getTileVisibility(tile)) {
XposedHelpers.callMethod(tile, "longClick");
}
return true;
}
};
try {
XposedHelpers.callMethod(tileView, "init", click, clickSecondary, longClick);
} catch (Throwable t) {
try {
XposedHelpers.callMethod(tileView, "init", click, clickSecondary);
} catch (Throwable t2) {
try {
XposedHelpers.callMethod(tileView, "initlongClickListener", longClick);
XposedHelpers.callMethod(tileView, "init", click, clickSecondary);
} catch (Throwable t3) {
try {
XposedHelpers.callMethod(tileView, "init", click, longClick);
} catch (Throwable t4) {
XposedHook.logE(TAG, "Couldn't init click listeners", null);
}
}
}
}
try {
XposedHelpers.callMethod(tileView, "setDual", false);
} catch (Throwable t) { // CM13
try {
XposedHelpers.callMethod(tileView, "setDual", false, false);
} catch (Throwable ignore) { // Other ROMs
}
}
try {
XposedHelpers.callMethod(tileView, "onStateChanged", XposedHelpers.callMethod(tile, "getState"));
} catch (Throwable t) {
XposedHelpers.callMethod(tileView, "onStateChanged", XposedHelpers.getObjectField(tile, "mState"));
}
View iconView = null;
int children = tileView.getChildCount();
for (int i = 0; i < children; i++) {
View child = tileView.getChildAt(i);
// no complex "getResources().getIdenifier("blah", "blah", "blah")"? I love it!
// FrameLayout is the container of the signal state icons
if (child.getId() == android.R.id.icon || child instanceof FrameLayout) {
child.setVisibility(VISIBLE);
iconView = child;
if (mShowPercent && iconView instanceof FrameLayout) {
if (((FrameLayout) iconView).getChildAt(0) != null) {
View frameChild = ((FrameLayout) iconView).getChildAt(0);
if (frameChild instanceof BatteryTile.BatteryView) {
BatteryTile.BatteryView batteryView = (BatteryTile.BatteryView) frameChild;
batteryView.setShowPercent(true);
}
}
}
} else {
child.setVisibility(GONE);
}
}
XposedHelpers.setAdditionalInstanceField(tile, KEY_QUICKQS_TILEVIEW, tileView);
if (getChildCount() != 0) {
// Add a spacer.
addView(new Space(getContext()), getChildCount(), generateSpaceParams());
}
if (iconView != null) {
((ViewGroup) iconView.getParent()).removeView(iconView);
addViewToLayout(iconView, getChildCount(), click, longClick);
} else {
addView(tileView, getChildCount(), generateOriginalLayoutParams());
}
}
private void addViewToLayout(View view, int position, OnClickListener click, OnLongClickListener longClick) {
view.setClickable(false);
RelativeLayout container = new RelativeLayout(view.getContext());
container.setClickable(true);
container.setOnClickListener(click);
container.setOnLongClickListener(longClick);
container.setBackground(newTileBackground());
container.addView(view, generateLayoutParams());
new GlobalLayoutListener(container);
addView(container, position, generateContainerLayoutParams());
mIconViews.add(view);
}
private class GlobalLayoutListener {
private final View mView;
GlobalLayoutListener(View view) {
mView = view;
mView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
mView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
mView.getBackground().setHotspot(mView.getWidth() / 2, mView.getHeight() / 2);
}
});
}
}
public void removeTiles() {
removeAllViews();
}
private RelativeLayout.LayoutParams generateLayoutParams() {
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, mIconSizePx);
lp.addRule(RelativeLayout.CENTER_IN_PARENT);
return lp;
}
private LayoutParams generateOriginalLayoutParams() {
int i = mRes.getDimensionPixelSize(R.dimen.qs_quick_tile_size);
LayoutParams layoutparams = new LayoutParams(i, i);
layoutparams.gravity = Gravity.CENTER;
return layoutparams;
}
private LayoutParams generateContainerLayoutParams() {
int i = mRes.getDimensionPixelSize(R.dimen.qs_quick_tile_size);
LayoutParams layoutparams = new LayoutParams(i, i);
layoutparams.gravity = Gravity.CENTER;
return layoutparams;
}
private LayoutParams generateSpaceParams() {
LayoutParams layoutparams = new LayoutParams(0, mRes.getDimensionPixelSize(R.dimen.qs_quick_tile_size));
layoutparams.weight = 1.0F;
layoutparams.gravity = Gravity.CENTER;
return layoutparams;
}
private Drawable newTileBackground() {
final int[] attrs = new int[]{android.R.attr.selectableItemBackgroundBorderless};
final TypedArray ta = getContext().obtainStyledAttributes(attrs);
final Drawable d = ta.getDrawable(0);
ta.recycle();
return d;
}
@Override
public boolean hasOverlappingRendering() {
return false;
}
}
private boolean getTileVisibility(Object tile) {
Object state = XposedHelpers.getObjectField(tile, "mState");
return XposedHelpers.getBooleanField(state, "visible");
}
}