All Downloads are FREE. Search and download functionalities are using the official Maven repository.

fr.nelaupe.spreadsheetlib.SpreadSheetView Maven / Gradle / Ivy

/*
 * Copyright 2015-present Lucas Nelaupe
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package fr.nelaupe.spreadsheetlib;

import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.TypedArray;
import android.os.Build;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import fr.nelaupe.spreadsheetlib.view.ArrowButton;
import fr.nelaupe.spreadsheetlib.view.DispatcherHorizontalScrollView;

/**
 * Created with IntelliJ
 * Created by Lucas Nelaupe
 * Date 26/03/15
 */
@SuppressWarnings({"unused", "unchecked"})
public class SpreadSheetView extends LinearLayout implements View.OnClickListener {

    private final float screenDensity;
    private final Context mContext;
    private final TableRow.LayoutParams wrapWrapTableRowParams;
    private List mData;
    private Map mFixedViewData;
    private String mPreviousID;
    private boolean mInvert;
    private TableLayout mHeader;
    private TableLayout mTable;
    private TableLayout mFixed;
    private TableLayout mFixedHeader;
    private OnItemClickListener mItemClickListener;
    private OnSortingListener mSortingListener;

    private int mHeaderBackgroundColor;
    private int mHeaderTextColor;
    private int mTextColor;

    private float mRowHeight;
    private float mHeaderTextSize;
    private float mTextSize;
    private float mMinFixedRowWidth;

    public SpreadSheetView(Context context) {
        super(context);
        wrapWrapTableRowParams = new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT, Gravity.CENTER);
        mContext = context;
        screenDensity = getContext().getResources().getDisplayMetrics().density;
        init();
    }

    public SpreadSheetView(Context context, AttributeSet attrs) {
        super(context, attrs);
        wrapWrapTableRowParams = new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT, Gravity.CENTER);
        mContext = context;
        screenDensity = getContext().getResources().getDisplayMetrics().density;
        parseAttribute(context, attrs);
        init();
    }

    public SpreadSheetView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        wrapWrapTableRowParams = new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT, Gravity.CENTER);
        mContext = context;
        screenDensity = getContext().getResources().getDisplayMetrics().density;
        parseAttribute(context, attrs);
        init();
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public SpreadSheetView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        wrapWrapTableRowParams = new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT, Gravity.CENTER);
        mContext = context;
        screenDensity = getContext().getResources().getDisplayMetrics().density;
        parseAttribute(context, attrs);
        init();
    }

    private void parseAttribute(Context context, AttributeSet attrs) {

        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.sheet);

        final int N = a.getIndexCount();
        for (int i = 0; i < N; ++i) {
            int attr = a.getIndex(i);
            if (attr == R.styleable.sheet_headerColor) {
                mHeaderBackgroundColor = a.getColor(attr, 0);
            } else if (attr == R.styleable.sheet_headerTextSize) {
                mHeaderTextSize = a.getDimensionPixelSize(attr, 0);
            } else if (attr == R.styleable.sheet_textSize) {
                mTextSize = a.getDimensionPixelSize(attr, 0);
            } else if (attr == R.styleable.sheet_textColor) {
                mTextColor = a.getColor(attr, 0);
            } else if (attr == R.styleable.sheet_headerTextColor) {
                mHeaderTextColor = a.getColor(attr, 0);
            } else if (attr == R.styleable.sheet_rowHeight) {
                mRowHeight = a.getDimensionPixelSize(attr, 0);
            } else if (attr == R.styleable.sheet_minFixedRowWidth) {
                mMinFixedRowWidth = a.getDimensionPixelSize(attr, 0);
            }
        }
        a.recycle();
    }

    private void init() {
        mData = new ArrayList<>();
        mFixedViewData = new HashMap<>();
        mPreviousID = "";
        mInvert = false;
        wrapWrapTableRowParams.gravity = Gravity.CENTER;

        LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View inflatedView = inflater.inflate(R.layout.spread_sheet_layout, this, true);

        mHeader = (TableLayout) inflatedView.findViewById(R.id.table_header);
        mTable = (TableLayout) inflatedView.findViewById(R.id.scrollable_part);
        mFixed = (TableLayout) inflatedView.findViewById(R.id.fixed_column);
        mFixedHeader = (TableLayout) inflatedView.findViewById(R.id.fixed_column_header);

        DispatcherHorizontalScrollView scrollViewTab = (DispatcherHorizontalScrollView) inflatedView.findViewById(R.id.scrollViewHorizontal);
        DispatcherHorizontalScrollView scrollViewHeader = (DispatcherHorizontalScrollView) inflatedView.findViewById(R.id.scrollViewHorizontalHeader);
        scrollViewHeader.setHorizontalScrollBarEnabled(false);

        scrollViewTab.setTarget(scrollViewHeader);
        scrollViewHeader.setTarget(scrollViewTab);
        scrollViewTab.setHorizontalScrollBarEnabled(true);

        invalidate();
    }

    /*
     *  Data
     */
    public List getData() {
        return mData;
    }

    public void add(SpreadSheetData data) {
        mData.add(data);
    }

    public void addAll(List data) {
        mData.addAll(data);
    }

    public void addFixedView(String name, int layout) {
        mFixedViewData.put(name, layout);
    }

    /*
     *  Colors parameters
     */
    public int getHeaderColor() {
        return (mHeaderBackgroundColor == 0) ? getResources().getColor(R.color.header_color) : mHeaderBackgroundColor;
    }

    public void setHeaderColor(int color) {
        mHeaderBackgroundColor = color;
    }

    public float getTextSize() {
        return (mTextSize == 0) ? getResources().getDimension(R.dimen.text) : mTextSize;
    }

    public void setTextSize(int textSize) {
        this.mTextSize = textSize;
    }

    public float getHeaderTextSize() {
        return (mHeaderTextSize == 0) ? getResources().getDimension(R.dimen.text) : mHeaderTextSize;
    }

    public void setHeaderTextSize(int headerTextSize) {
        this.mHeaderTextSize = headerTextSize;
    }

    public int getTextColor() {
        return (mTextColor == 0) ? getResources().getColor(R.color.text) : mTextColor;
    }

    public void setTextColor(int mTextColor) {
        this.mTextColor = mTextColor;
    }

    public int getHeaderTextColor() {
        return (mHeaderTextColor == 0) ? getResources().getColor(R.color.white) : mHeaderTextColor;
    }

    public void setHeaderTextColor(int headerTextColor) {
        this.mHeaderTextColor = headerTextColor;
    }

    public int getRowHeight() {
        return (int) ((mRowHeight == 0) ? getResources().getDimension(R.dimen.rowHeight) : mRowHeight);
    }

    public void setRowHeight(float rowHeight) {
        mRowHeight = computeSize(rowHeight);
    }

    public int getMinFixedRowWidth() {
        return (int) ((mMinFixedRowWidth == 0) ? getResources().getDimension(R.dimen.minFixedRowWidth) : mMinFixedRowWidth);
    }

    public void setMinFixedRowWidth(float minFixedRowWidth) {
        mMinFixedRowWidth = computeSize(minFixedRowWidth);
    }

    private int computeSize(float size) {
        return (int) (size * screenDensity + 0.5f);
    }

    /*
     *  Click
     */
    @Override
    public void onClick(View v) {

        int i = v.getId();

        if (i == R.id.filter) {
            SpreadSheetData cls = mData.get(0);
            try {
                String filterName = String.valueOf(v.getTag(R.id.filter_name));
                if(!TextUtils.isEmpty(filterName)) {
                    Comparator comparator = (Comparator) cls.getClass().getDeclaredField(filterName).get(mData.get(0));
                    doSorting(v, comparator);
                }

            } catch (Exception e) {
                e.printStackTrace();
            }

        } else if (i == R.id.item) {
            SpreadSheetData item = (SpreadSheetData) v.getTag(R.id.item_data);
            onItemClick(item);
        }
    }

    public void setOnItemClickListener(OnItemClickListener listener) {
        mItemClickListener = listener;
    }

    public void onItemClick(SpreadSheetData item) {
        if (mItemClickListener != null) {
            mItemClickListener.onItemClick(item);
        }
    }

    public void setOnSortingListener(OnSortingListener mSortingListener) {
        this.mSortingListener = mSortingListener;
    }

    public void onSort() {
        if (mSortingListener != null) {
            mSortingListener.onSort();
        }
    }

    /*
     *  View
     */
    private void addFixedHeader() {
        TableRow row = new TableRow(mContext);
        row.setLayoutParams(wrapWrapTableRowParams);
        row.setGravity(Gravity.CENTER);
        row.setBackgroundColor(getHeaderColor());
        for (String name : mFixedViewData.keySet()) {
            Button textView = new Button(mContext);
            textView.setText(name);
            textView.setTextColor(getHeaderTextColor());
            textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, getHeaderTextSize());
            textView.setGravity(Gravity.CENTER);
            textView.setWidth(getMinFixedRowWidth());
            textView.setHeight(getRowHeight());
            textView.setBackground(null);
            row.addView(textView);
        }

        mFixedHeader.addView(row);
    }

    private void addHeader() {
        SpreadSheetData cls = mData.get(0);
        TableRow row = new TableRow(mContext);
        row.setLayoutParams(wrapWrapTableRowParams);
        row.setGravity(Gravity.CENTER);
        row.setBackgroundColor(getHeaderColor());

        for (Field field : cls.getClass().getDeclaredFields()) {
            for (Annotation annotation : field.getDeclaredAnnotations()) {
                if (annotation instanceof SpreadSheetCell) {
                    SpreadSheetCell trueField = (SpreadSheetCell) annotation;
                    ArrowButton button = new ArrowButton(mContext);
                    button.setWidth(computeSize(trueField.size()));
                    button.setHeight(getRowHeight());
                    button.setTextColor(getHeaderTextColor());
                    button.setBackground(null);
                    button.setText(trueField.name());
                    button.setTextSize(TypedValue.COMPLEX_UNIT_PX, getHeaderTextSize());
                    button.setCompoundDrawablesWithIntrinsicBounds(R.drawable.icr_arrow_selector_sort, 0, R.drawable.arrow_empty, 0);
                    button.setOnClickListener(this);
                    button.setId(R.id.filter);
                    if(!TextUtils.isEmpty(trueField.filterName())) {
                        button.setTag(R.id.filter_name, trueField.filterName());
                    }
                    row.addView(button);
                }
            }
        }
        mHeader.addView(row);
    }

    private void AddFixedRow(boolean colorBool) {
        TableRow row = new TableRow(mContext);
        row.setLayoutParams(wrapWrapTableRowParams);
        row.setGravity(Gravity.CENTER);
        row.setBackgroundColor(mContext.getResources().getColor(colorBool ? R.color.white : R.color.grey_cell));
        for (Map.Entry entry : mFixedViewData.entrySet()) {
            LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            View view = inflater.inflate(entry.getValue(), null);
            view.setMinimumHeight(getRowHeight());
            view.setMinimumWidth(getMinFixedRowWidth());
            row.addView(view);
        }

        mFixed.addView(row);
    }

    private void addRow() {
        Boolean colorBool = true;
        int nb = 0;
        for (SpreadSheetData resource : mData) {

            AddFixedRow(colorBool);

            TableRow row = new TableRow(mContext);
            row.setLayoutParams(wrapWrapTableRowParams);
            row.setGravity(Gravity.CENTER);
            row.setBackgroundColor(mContext.getResources().getColor(colorBool ? R.color.white : R.color.grey_cell));
            row.setId(R.id.item);
            row.setTag(R.id.item_data, resource);
            row.setOnClickListener(this);

            for (Field field : resource.getClass().getDeclaredFields()) {
                try {
                    for (Annotation annotation : field.getDeclaredAnnotations()) {
                        if (annotation instanceof SpreadSheetCell) {
                            SpreadSheetCell spreadSheetCell = (SpreadSheetCell) annotation;
                            TextView recyclableTextView = new TextView(mContext);
                            Object object = field.get(resource);
                            recyclableTextView.setText((object == null ? "" : object.toString()));
                            recyclableTextView.setTextColor(getTextColor());
                            recyclableTextView.setGravity(Gravity.CENTER);
                            recyclableTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, getTextSize());
                            recyclableTextView.setWidth(computeSize(spreadSheetCell.size()));
                            recyclableTextView.setHeight(getRowHeight());
                            row.addView(recyclableTextView);
                        }
                    }
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }

            colorBool = !colorBool;
            mTable.addView(row);
            nb++;
        }
    }

    public void clearData() {
        mData = new ArrayList<>();
    }

    public void invalidate() {
        if (mData.isEmpty()) return;

        mFixedHeader.removeAllViews();
        mHeader.removeAllViews();
        mFixed.removeAllViews();
        mTable.removeAllViews();

        addFixedHeader();
        addHeader();
        addRow();
    }

    private void invalidateContent() {
        mTable.removeAllViews();
        mFixed.removeAllViews();

        addRow();
    }

    /*
     *  Sorting
     */
    private void invert(View v) {
        Collections.reverse(mData);
        if (!mInvert) {
            setArrowDown((ArrowButton) v);
        } else {
            setArrowUP((ArrowButton) v);
        }
        mInvert = !mInvert;
    }

    private void sort(View v, Comparator comparator) {
        setArrowUP((ArrowButton) v);
        mPreviousID = String.valueOf(v.getTag(R.id.filter_name));
        mInvert = false;
        Collections.sort(mData, comparator);
    }

    private void doSorting(View v, Comparator comparator) {
        if (mPreviousID.equals(v.getTag(R.id.filter_name))) {
            invert(v);
        } else {
            sort(v, comparator);
        }
        onSort();
        invalidateContent();
    }

    private void resetArrow() {
        TableRow row = (TableRow) (mHeader).getChildAt(0);
        for (int i = 0; i < row.getChildCount(); ++i) {
            ArrowButton childAt = (ArrowButton) row.getChildAt(i);
            childAt.setState(ArrowButton.states.NONE);
        }
    }

    private void setArrowDown(ArrowButton view) {
        resetArrow();
        view.setState(ArrowButton.states.DONW);
    }

    private void setArrowUP(ArrowButton view) {
        resetArrow();
        view.setState(ArrowButton.states.UP);
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy