diff --git a/app/src/main/java/com/evrencoskun/tableviewsample/MainFragment.java b/app/src/main/java/com/evrencoskun/tableviewsample/MainFragment.java index efb25eda..c395033e 100644 --- a/app/src/main/java/com/evrencoskun/tableviewsample/MainFragment.java +++ b/app/src/main/java/com/evrencoskun/tableviewsample/MainFragment.java @@ -95,6 +95,11 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c // Let's get TableView mTableView = layout.findViewById(R.id.tableview); + mTableView.setSelectable(true); + mTableView.getSelectionHandler().setShadowEnabled(true); + mTableView.getSelectionHandler().setMultiSelectionEnabled(true); + mTableFilter = new Filter(mTableView); // Create an instance of a Filter and pass the + // created TableView. initializeTableView(); diff --git a/app/src/main/java/com/evrencoskun/tableviewsample/tableview/model/Cell.java b/app/src/main/java/com/evrencoskun/tableviewsample/tableview/model/Cell.java index 92f162eb..5ff287fe 100644 --- a/app/src/main/java/com/evrencoskun/tableviewsample/tableview/model/Cell.java +++ b/app/src/main/java/com/evrencoskun/tableviewsample/tableview/model/Cell.java @@ -17,7 +17,9 @@ package com.evrencoskun.tableviewsample.tableview.model; +import com.evrencoskun.tableview.adapter.recyclerview.holder.AbstractViewHolder; import com.evrencoskun.tableview.filter.IFilterableModel; +import com.evrencoskun.tableview.handler.ISelectableModel; import com.evrencoskun.tableview.sort.ISortableModel; import androidx.annotation.NonNull; @@ -26,14 +28,14 @@ /** * Created by evrencoskun on 11/06/2017. */ - -public class Cell implements ISortableModel, IFilterableModel { +public class Cell implements ISortableModel, IFilterableModel, ISelectableModel { @NonNull private String mId; @Nullable private Object mData; @NonNull private String mFilterKeyword; + private AbstractViewHolder.SelectionState mSelectionState = AbstractViewHolder.SelectionState.UNSELECTED; public Cell(@NonNull String id, @Nullable Object data) { this.mId = id; @@ -75,4 +77,15 @@ public void setData(@Nullable Object data) { public String getFilterableKeyword() { return mFilterKeyword; } + + @Override + public AbstractViewHolder.SelectionState getSelectionState() { + return mSelectionState; + } + + @NonNull + @Override + public void setSelectionState(AbstractViewHolder.SelectionState selectionState) { + mSelectionState = selectionState; + } } diff --git a/tableview/src/main/java/com/evrencoskun/tableview/ITableView.java b/tableview/src/main/java/com/evrencoskun/tableview/ITableView.java index c424bd64..c8957cc2 100644 --- a/tableview/src/main/java/com/evrencoskun/tableview/ITableView.java +++ b/tableview/src/main/java/com/evrencoskun/tableview/ITableView.java @@ -61,6 +61,10 @@ public interface ITableView { boolean isSortable(); + boolean isSelectable(); + + void setSelectable(boolean selectable); + @NonNull Context getContext(); diff --git a/tableview/src/main/java/com/evrencoskun/tableview/TableView.java b/tableview/src/main/java/com/evrencoskun/tableview/TableView.java index a737d9c4..d11a6696 100644 --- a/tableview/src/main/java/com/evrencoskun/tableview/TableView.java +++ b/tableview/src/main/java/com/evrencoskun/tableview/TableView.java @@ -116,6 +116,7 @@ public class TableView extends FrameLayout implements ITableView { private boolean mAllowClickInsideRowHeader = false; private boolean mAllowClickInsideColumnHeader = false; private boolean mIsSortable; + private boolean mIsSelectable; public TableView(@NonNull Context context) { super(context); @@ -378,6 +379,16 @@ public boolean isSortable() { return mIsSortable; } + @Override + public boolean isSelectable() { + return mIsSelectable; + } + + @Override + public void setSelectable(boolean selectable) { + mIsSelectable = selectable; + } + public void setShowHorizontalSeparators(boolean showSeparators) { this.mShowHorizontalSeparators = showSeparators; } @@ -583,42 +594,37 @@ public boolean isRowVisible(int row) { return mVisibilityHandler.isRowVisible(row); } + + + public void setSelectedRow(int row) { + mSelectionHandler.setSelectedRowPosition(row); + } + /** * Returns the index of the selected row, -1 if no row is selected. */ public int getSelectedRow() { - return mSelectionHandler.getSelectedRowPosition(); - } - - public void setSelectedRow(int row) { - // Find the row header view holder which is located on row position. - AbstractViewHolder rowViewHolder = (AbstractViewHolder) getRowHeaderRecyclerView() - .findViewHolderForAdapterPosition(row); - - - mSelectionHandler.setSelectedRowPosition(rowViewHolder, row); + //TODO: reuse logic in mSelectionHandler.rowHasItemSelected + // to return list of selected rows + return -1;//mSelectionHandler.getSelectedRowPosition(); } /** * Returns the index of the selected column, -1 if no column is selected. */ public int getSelectedColumn() { - return mSelectionHandler.getSelectedColumnPosition(); + //TODO: reuse logic in mSelectionHandler.columnHasItemSelected + // to return list of selected columns + return -1; //mSelectionHandler.getSelectedColumnPosition(); } public void setSelectedColumn(int column) { - // Find the column view holder which is located on column position . - AbstractViewHolder columnViewHolder = (AbstractViewHolder) getColumnHeaderRecyclerView() - .findViewHolderForAdapterPosition(column); - - mSelectionHandler.setSelectedColumnPosition(columnViewHolder, column); + mSelectionHandler.setSelectedColumnPosition(column); } public void setSelectedCell(int column, int row) { // Find the cell view holder which is located on x,y (column,row) position. - AbstractViewHolder cellViewHolder = getCellLayoutManager().getCellViewHolder(column, row); - - mSelectionHandler.setSelectedCellPositions(cellViewHolder, column, row); + mSelectionHandler.setSelectedCellPositions(row, column); } @NonNull diff --git a/tableview/src/main/java/com/evrencoskun/tableview/adapter/AbstractTableAdapter.java b/tableview/src/main/java/com/evrencoskun/tableview/adapter/AbstractTableAdapter.java index b72260a2..6b84290f 100644 --- a/tableview/src/main/java/com/evrencoskun/tableview/adapter/AbstractTableAdapter.java +++ b/tableview/src/main/java/com/evrencoskun/tableview/adapter/AbstractTableAdapter.java @@ -29,6 +29,7 @@ import com.evrencoskun.tableview.adapter.recyclerview.CellRecyclerViewAdapter; import com.evrencoskun.tableview.adapter.recyclerview.ColumnHeaderRecyclerViewAdapter; import com.evrencoskun.tableview.adapter.recyclerview.RowHeaderRecyclerViewAdapter; +import com.evrencoskun.tableview.adapter.recyclerview.holder.AbstractViewHolder; import java.util.ArrayList; import java.util.List; @@ -346,4 +347,32 @@ public void addAdapterDataSetChangedListener(@NonNull AdapterDataSetChangedListe dataSetChangedListeners.add(listener); } + + public boolean isSelectable(){ + return mTableView.isSelectable(); + } + + public int getColorForSelection(AbstractViewHolder.SelectionState selectionState) { + switch (selectionState) { + case SELECTED: + return mTableView.getSelectedColor(); + case SHADOWED: + return mTableView.getShadowColor(); + } + return mTableView.getUnSelectedColor(); + } + + public int getColumnHeaderItemCount() { + if (mColumnHeaderItems != null) { + return mColumnHeaderItems.size(); + } + return 0; + } + + public int getRowHeaderItemCount() { + if (mRowHeaderItems != null) { + return mRowHeaderItems.size(); + } + return 0; + } } diff --git a/tableview/src/main/java/com/evrencoskun/tableview/adapter/ITableAdapter.java b/tableview/src/main/java/com/evrencoskun/tableview/adapter/ITableAdapter.java index 6e414d3a..bc794865 100644 --- a/tableview/src/main/java/com/evrencoskun/tableview/adapter/ITableAdapter.java +++ b/tableview/src/main/java/com/evrencoskun/tableview/adapter/ITableAdapter.java @@ -60,6 +60,8 @@ public interface ITableAdapter { ITableView getTableView(); + int getColorForSelection(AbstractViewHolder.SelectionState selectionState); + /** * Sets the listener for changes of data set on the TableView. * diff --git a/tableview/src/main/java/com/evrencoskun/tableview/adapter/recyclerview/CellRecyclerViewAdapter.java b/tableview/src/main/java/com/evrencoskun/tableview/adapter/recyclerview/CellRecyclerViewAdapter.java index 145b62ea..d1be70ba 100644 --- a/tableview/src/main/java/com/evrencoskun/tableview/adapter/recyclerview/CellRecyclerViewAdapter.java +++ b/tableview/src/main/java/com/evrencoskun/tableview/adapter/recyclerview/CellRecyclerViewAdapter.java @@ -133,25 +133,7 @@ public void onViewAttachedToWindow(@NonNull AbstractViewHolder holder) { .scrollToPositionWithOffset(scrollHandler.getColumnPosition(), scrollHandler .getColumnPositionOffset()); - SelectionHandler selectionHandler = mTableView.getSelectionHandler(); - - if (selectionHandler.isAnyColumnSelected()) { - - AbstractViewHolder cellViewHolder = (AbstractViewHolder) viewHolder.recyclerView - .findViewHolderForAdapterPosition(selectionHandler.getSelectedColumnPosition()); - - if (cellViewHolder != null) { - // Control to ignore selection color - if (!mTableView.isIgnoreSelectionColors()) { - cellViewHolder.setBackgroundColor(mTableView.getSelectedColor()); - } - cellViewHolder.setSelected(SelectionState.SELECTED); - - } - } else if (selectionHandler.isRowSelected(holder.getAdapterPosition())) { - selectionHandler.changeSelectionOfRecyclerView(viewHolder.recyclerView, - SelectionState.SELECTED, mTableView.getSelectedColor()); - } + // TODO? } @@ -202,6 +184,28 @@ public void notifyCellDataSetChanged() { } } + @Nullable + public C getItem(int rowPosition, int columnPosition) { + if (mItemList.size() > rowPosition) { + List row = (List) mItemList.get(rowPosition); + if(row.size() > columnPosition) { + return row.get(columnPosition); + } + } + return null; + } + + /** + * This method helps to get cell item model that is located on given row position. + * + * @param rowPosition + */ + public List getRowItems(int rowPosition) { + List cellItems = new ArrayList<>(); + + return (List) mItemList.get(rowPosition); + } + /** * This method helps to get cell item model that is located on given column position. * diff --git a/tableview/src/main/java/com/evrencoskun/tableview/adapter/recyclerview/CellRowRecyclerViewAdapter.java b/tableview/src/main/java/com/evrencoskun/tableview/adapter/recyclerview/CellRowRecyclerViewAdapter.java index de41e706..3e3d35c1 100644 --- a/tableview/src/main/java/com/evrencoskun/tableview/adapter/recyclerview/CellRowRecyclerViewAdapter.java +++ b/tableview/src/main/java/com/evrencoskun/tableview/adapter/recyclerview/CellRowRecyclerViewAdapter.java @@ -26,6 +26,7 @@ import com.evrencoskun.tableview.adapter.ITableAdapter; import com.evrencoskun.tableview.adapter.recyclerview.holder.AbstractViewHolder; import com.evrencoskun.tableview.adapter.recyclerview.holder.AbstractViewHolder.SelectionState; +import com.evrencoskun.tableview.handler.ISelectableModel; /** * Created by evrencoskun on 10/06/2017. @@ -52,8 +53,24 @@ public AbstractViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int view } @Override - public void onBindViewHolder(@NonNull final AbstractViewHolder holder, final int xPosition) { - mTableAdapter.onBindCellViewHolder(holder, getItem(xPosition), xPosition, mYPosition); + public void onBindViewHolder(@NonNull final AbstractViewHolder viewHolder, final int xPosition) { + if (mTableAdapter != null) { + Object value = getItem(xPosition); + + // Apply Selection Style + if (mTableAdapter.getTableView().isSelectable()) { + if (value instanceof ISelectableModel) { + viewHolder.setSelected(((ISelectableModel) value).getSelectionState()); + int color = mTableAdapter.getColorForSelection(((ISelectableModel) value).getSelectionState()); + viewHolder.setBackgroundColor(color); + } else if (value != null) { + // trigger exception, if isSelectable, Cells MUST implements ISelectableModel + throw new ClassCastException("Item at position (" + mYPosition + ", " + xPosition + ") must implement ISelectableModel to be selectable."); + } + } + + mTableAdapter.onBindCellViewHolder(viewHolder, value, xPosition, mYPosition); + } } public int getYPosition() { @@ -73,22 +90,23 @@ public int getItemViewType(int position) { public void onViewAttachedToWindow(@NonNull AbstractViewHolder viewHolder) { super.onViewAttachedToWindow(viewHolder); - SelectionState selectionState = mTableView.getSelectionHandler().getCellSelectionState - (viewHolder.getAdapterPosition(), mYPosition); + if (mTableAdapter.getTableView().isSelectable()) { + SelectionState selectionState = mTableView.getSelectionHandler() + .getCellSelectionState(viewHolder.getAdapterPosition(), mYPosition); - // Control to ignore selection color - if (!mTableView.isIgnoreSelectionColors()) { + // Control to ignore selection color + if (!mTableView.isIgnoreSelectionColors()) { - // Change the background color of the view considering selected row/cell position. - if (selectionState == SelectionState.SELECTED) { - viewHolder.setBackgroundColor(mTableView.getSelectedColor()); - } else { - viewHolder.setBackgroundColor(mTableView.getUnSelectedColor()); + // Change the background color of the view considering selected row/cell position. + if (selectionState == SelectionState.SELECTED) { + viewHolder.setBackgroundColor(mTableView.getSelectedColor()); + } else { + viewHolder.setBackgroundColor(mTableView.getUnSelectedColor()); + } } + // Change selection status + viewHolder.setSelected(selectionState); } - - // Change selection status - viewHolder.setSelected(selectionState); } @Override diff --git a/tableview/src/main/java/com/evrencoskun/tableview/adapter/recyclerview/ColumnHeaderRecyclerViewAdapter.java b/tableview/src/main/java/com/evrencoskun/tableview/adapter/recyclerview/ColumnHeaderRecyclerViewAdapter.java index da5de38e..cfb988f1 100644 --- a/tableview/src/main/java/com/evrencoskun/tableview/adapter/recyclerview/ColumnHeaderRecyclerViewAdapter.java +++ b/tableview/src/main/java/com/evrencoskun/tableview/adapter/recyclerview/ColumnHeaderRecyclerViewAdapter.java @@ -27,7 +27,7 @@ import com.evrencoskun.tableview.adapter.ITableAdapter; import com.evrencoskun.tableview.adapter.recyclerview.holder.AbstractSorterViewHolder; import com.evrencoskun.tableview.adapter.recyclerview.holder.AbstractViewHolder; -import com.evrencoskun.tableview.adapter.recyclerview.holder.AbstractViewHolder.SelectionState; +import com.evrencoskun.tableview.handler.ISelectableModel; import com.evrencoskun.tableview.sort.ColumnSortHelper; import com.evrencoskun.tableview.sort.SortState; @@ -57,8 +57,22 @@ public AbstractViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int view } @Override - public void onBindViewHolder(@NonNull AbstractViewHolder holder, int position) { - mTableAdapter.onBindColumnHeaderViewHolder(holder, getItem(position), position); + public void onBindViewHolder(@NonNull AbstractViewHolder viewHolder, int position) { + Object value = getItem(position); + + // Apply Selection Style + if (mTableAdapter.getTableView().isSelectable()) { + if (value instanceof ISelectableModel) { + viewHolder.setSelected(((ISelectableModel) value).getSelectionState()); + final int color = mTableAdapter.getColorForSelection(((ISelectableModel) value).getSelectionState()); + viewHolder.setBackgroundColor(color); + } else if(value != null){ + // trigger exception, if isSelectable, Cells MUST implements ISelectableModel + throw new ClassCastException("Item at position " + position + " must implement ISelectableModel to be selectable."); + } + } + + mTableAdapter.onBindColumnHeaderViewHolder(viewHolder, value, position); } @Override @@ -70,20 +84,19 @@ public int getItemViewType(int position) { public void onViewAttachedToWindow(@NonNull AbstractViewHolder viewHolder) { super.onViewAttachedToWindow(viewHolder); - SelectionState selectionState = mTableView.getSelectionHandler().getColumnSelectionState - (viewHolder.getAdapterPosition()); + if (mTableAdapter.getTableView().isSelectable()) { + // Control to ignore selection color + if (!mTableView.isIgnoreSelectionColors()) { - // Control to ignore selection color - if (!mTableView.isIgnoreSelectionColors()) { + // Change background color of the view considering it's selected state + mTableView.getSelectionHandler() + .changeColumnBackgroundColorBySelectionStatus(viewHolder, viewHolder.getSelected()); + } - // Change background color of the view considering it's selected state - mTableView.getSelectionHandler().changeColumnBackgroundColorBySelectionStatus - (viewHolder, selectionState); + // Change selection status + viewHolder.setSelected(viewHolder.getSelected()); } - // Change selection status - viewHolder.setSelected(selectionState); - // Control whether the TableView is sortable or not. if (mTableView.isSortable()) { if (viewHolder instanceof AbstractSorterViewHolder) { diff --git a/tableview/src/main/java/com/evrencoskun/tableview/adapter/recyclerview/RowHeaderRecyclerViewAdapter.java b/tableview/src/main/java/com/evrencoskun/tableview/adapter/recyclerview/RowHeaderRecyclerViewAdapter.java index 81aa53ac..555a7481 100644 --- a/tableview/src/main/java/com/evrencoskun/tableview/adapter/recyclerview/RowHeaderRecyclerViewAdapter.java +++ b/tableview/src/main/java/com/evrencoskun/tableview/adapter/recyclerview/RowHeaderRecyclerViewAdapter.java @@ -26,9 +26,10 @@ import com.evrencoskun.tableview.ITableView; import com.evrencoskun.tableview.adapter.ITableAdapter; import com.evrencoskun.tableview.adapter.recyclerview.holder.AbstractViewHolder; -import com.evrencoskun.tableview.adapter.recyclerview.holder.AbstractViewHolder.SelectionState; +import com.evrencoskun.tableview.handler.ISelectableModel; import com.evrencoskun.tableview.sort.RowHeaderSortHelper; + import java.util.List; /** @@ -55,8 +56,22 @@ public AbstractViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int view } @Override - public void onBindViewHolder(@NonNull AbstractViewHolder holder, int position) { - mTableAdapter.onBindRowHeaderViewHolder(holder, getItem(position), position); + public void onBindViewHolder(@NonNull AbstractViewHolder viewHolder, int position) { + Object value = getItem(position); + + // Apply Selection Style + if (mTableAdapter.getTableView().isSelectable()) { + if (value instanceof ISelectableModel) { + viewHolder.setSelected(((ISelectableModel) value).getSelectionState()); + int color = mTableAdapter.getColorForSelection(((ISelectableModel) value).getSelectionState()); + viewHolder.setBackgroundColor(color); + } else if (value != null) { + // trigger exception, if isSelectable, Cells MUST implements ISelectableModel + throw new ClassCastException("Item at position " + position + " must implement ISelectableModel to be selectable."); + } + } + + mTableAdapter.onBindRowHeaderViewHolder(viewHolder, value, position); } @Override @@ -68,19 +83,18 @@ public int getItemViewType(int position) { public void onViewAttachedToWindow(@NonNull AbstractViewHolder viewHolder) { super.onViewAttachedToWindow(viewHolder); - SelectionState selectionState = mTableView.getSelectionHandler().getRowSelectionState - (viewHolder.getAdapterPosition()); + if (mTableAdapter.getTableView().isSelectable()) { - // Control to ignore selection color - if (!mTableView.isIgnoreSelectionColors()) { + // Control to ignore selection color + if (!mTableView.isIgnoreSelectionColors()) { + // Change background color of the view considering it's selected state + mTableView.getSelectionHandler().changeRowBackgroundColorBySelectionStatus + (viewHolder, viewHolder.getSelected()); + } - // Change background color of the view considering it's selected state - mTableView.getSelectionHandler().changeRowBackgroundColorBySelectionStatus - (viewHolder, selectionState); + // Change selection status + viewHolder.setSelected(viewHolder.getSelected()); } - - // Change selection status - viewHolder.setSelected(selectionState); } @NonNull diff --git a/tableview/src/main/java/com/evrencoskun/tableview/adapter/recyclerview/holder/AbstractViewHolder.java b/tableview/src/main/java/com/evrencoskun/tableview/adapter/recyclerview/holder/AbstractViewHolder.java index b51b6206..0b26afc7 100644 --- a/tableview/src/main/java/com/evrencoskun/tableview/adapter/recyclerview/holder/AbstractViewHolder.java +++ b/tableview/src/main/java/com/evrencoskun/tableview/adapter/recyclerview/holder/AbstractViewHolder.java @@ -48,6 +48,10 @@ public void setSelected(@NonNull SelectionState selectionState) { } } + public SelectionState getSelected() { + return m_eState; + } + public boolean isSelected() { return m_eState == SelectionState.SELECTED; } diff --git a/tableview/src/main/java/com/evrencoskun/tableview/handler/ISelectableModel.java b/tableview/src/main/java/com/evrencoskun/tableview/handler/ISelectableModel.java new file mode 100644 index 00000000..bb5b8ecc --- /dev/null +++ b/tableview/src/main/java/com/evrencoskun/tableview/handler/ISelectableModel.java @@ -0,0 +1,12 @@ +package com.evrencoskun.tableview.handler; + +import com.evrencoskun.tableview.adapter.recyclerview.holder.AbstractViewHolder; + +/** + * Created by cedricferry on 8/2/18. + */ + +public interface ISelectableModel { + AbstractViewHolder.SelectionState getSelectionState(); + void setSelectionState(AbstractViewHolder.SelectionState selectionState); +} diff --git a/tableview/src/main/java/com/evrencoskun/tableview/handler/PreferencesHandler.java b/tableview/src/main/java/com/evrencoskun/tableview/handler/PreferencesHandler.java index 5ad557ff..d0fdf922 100644 --- a/tableview/src/main/java/com/evrencoskun/tableview/handler/PreferencesHandler.java +++ b/tableview/src/main/java/com/evrencoskun/tableview/handler/PreferencesHandler.java @@ -44,8 +44,9 @@ public Preferences savePreferences() { preferences.columnPositionOffset = scrollHandler.getColumnPositionOffset(); preferences.rowPosition = scrollHandler.getRowPosition(); preferences.rowPositionOffset = scrollHandler.getRowPositionOffset(); - preferences.selectedColumnPosition = selectionHandler.getSelectedColumnPosition(); - preferences.selectedRowPosition = selectionHandler.getSelectedRowPosition(); + // TODO + //preferences.selectedColumnPosition = selectionHandler.getSelectedColumnPosition(); + //preferences.selectedRowPosition = selectionHandler.getSelectedRowPosition(); return preferences; } diff --git a/tableview/src/main/java/com/evrencoskun/tableview/handler/SelectionHandler.java b/tableview/src/main/java/com/evrencoskun/tableview/handler/SelectionHandler.java index 7ab574ff..4931c3eb 100644 --- a/tableview/src/main/java/com/evrencoskun/tableview/handler/SelectionHandler.java +++ b/tableview/src/main/java/com/evrencoskun/tableview/handler/SelectionHandler.java @@ -30,13 +30,19 @@ /** * Created by evrencoskun on 24/10/2017. + * Refactored by cedricferry on 10/02/2018 */ public class SelectionHandler { - public static final int UNSELECTED_POSITION = -1; - private int mSelectedRowPosition = UNSELECTED_POSITION; - private int mSelectedColumnPosition = UNSELECTED_POSITION; + public enum SELECTION_TYPE {NONE, CELLS, ROWS, COLUMNS} + + ; + + + private SELECTION_TYPE selectionType = SELECTION_TYPE.NONE; + + private boolean mMultiSelectionEnabled = false; private boolean shadowEnabled = true; @@ -65,182 +71,38 @@ public void setShadowEnabled(boolean shadowEnabled) { this.shadowEnabled = shadowEnabled; } - public void setSelectedCellPositions(@Nullable AbstractViewHolder selectedViewHolder, int column, int - row) { - this.setPreviousSelectedView(selectedViewHolder); - - this.mSelectedColumnPosition = column; - this.mSelectedRowPosition = row; - - if (shadowEnabled) { - selectedCellView(); - } - } - public void setSelectedColumnPosition(@Nullable AbstractViewHolder selectedViewHolder, int column) { - this.setPreviousSelectedView(selectedViewHolder); - - this.mSelectedColumnPosition = column; - - selectedColumnHeader(); - - // Set unselected others - mSelectedRowPosition = UNSELECTED_POSITION; - } - - public int getSelectedColumnPosition() { - return mSelectedColumnPosition; + setSelectedColumnPosition(column); } - public void setSelectedRowPosition(@Nullable AbstractViewHolder selectedViewHolder, int row) { - this.setPreviousSelectedView(selectedViewHolder); - - this.mSelectedRowPosition = row; - - selectedRowHeader(); - - // Set unselected others - mSelectedColumnPosition = UNSELECTED_POSITION; + public void setSelectedRowPosition(AbstractViewHolder selectedViewHolder, int row) { + setSelectedRowPosition(row); } - public int getSelectedRowPosition() { - return mSelectedRowPosition; + /** + * set selected state for one cell at (row, column) coordinates + * + * @param row + * @param column + */ + public void setSelectedCellPositions(int row, int column) { + setSelectedCellPositions(row, column, true); } - public void setPreviousSelectedView(@Nullable AbstractViewHolder viewHolder) { - restorePreviousSelectedView(); - - if (mPreviousSelectedViewHolder != null) { - // Change color - mPreviousSelectedViewHolder.setBackgroundColor(mTableView.getUnSelectedColor()); - // Change state - mPreviousSelectedViewHolder.setSelected(SelectionState.UNSELECTED); - } - - AbstractViewHolder oldViewHolder = mCellLayoutManager.getCellViewHolder - (getSelectedColumnPosition(), getSelectedRowPosition()); - - if (oldViewHolder != null) { - // Change color - oldViewHolder.setBackgroundColor(mTableView.getUnSelectedColor()); - // Change state - oldViewHolder.setSelected(SelectionState.UNSELECTED); - } - - this.mPreviousSelectedViewHolder = viewHolder; - - // Change color - mPreviousSelectedViewHolder.setBackgroundColor(mTableView.getSelectedColor()); - // Change state - mPreviousSelectedViewHolder.setSelected(SelectionState.SELECTED); - } - - private void restorePreviousSelectedView() { - if (mSelectedColumnPosition != UNSELECTED_POSITION && mSelectedRowPosition != - UNSELECTED_POSITION) { - unselectedCellView(); - } else if (mSelectedColumnPosition != UNSELECTED_POSITION) { - unselectedColumnHeader(); - } else if (mSelectedRowPosition != UNSELECTED_POSITION) { - unselectedRowHeader(); - } - } - - private void selectedRowHeader() { - // Change background color of the selected cell views - changeVisibleCellViewsBackgroundForRow(mSelectedRowPosition, true); - - // Change background color of the column headers to be shown as a shadow. - if (shadowEnabled) { - changeSelectionOfRecyclerView(mColumnHeaderRecyclerView, SelectionState.SHADOWED, - mTableView.getShadowColor()); - } - } - - private void unselectedRowHeader() { - changeVisibleCellViewsBackgroundForRow(mSelectedRowPosition, false); - - // Change background color of the column headers to be shown as a normal. - changeSelectionOfRecyclerView(mColumnHeaderRecyclerView, SelectionState.UNSELECTED, - mTableView.getUnSelectedColor()); - } - - private void selectedCellView() { - int shadowColor = mTableView.getShadowColor(); - - // Change background color of the row header which is located on Y Position of the cell - // view. - AbstractViewHolder rowHeader = (AbstractViewHolder) mRowHeaderRecyclerView - .findViewHolderForAdapterPosition(mSelectedRowPosition); - - // If view is null, that means the row view holder was already recycled. - if (rowHeader != null) { - // Change color - rowHeader.setBackgroundColor(shadowColor); - // Change state - rowHeader.setSelected(SelectionState.SHADOWED); - } - - // Change background color of the column header which is located on X Position of the cell - // view. - AbstractViewHolder columnHeader = (AbstractViewHolder) mColumnHeaderRecyclerView - .findViewHolderForAdapterPosition(mSelectedColumnPosition); - - if (columnHeader != null) { - // Change color - columnHeader.setBackgroundColor(shadowColor); - // Change state - columnHeader.setSelected(SelectionState.SHADOWED); - } - + public void setSelectedCellPositions(@Nullable AbstractViewHolder selectedViewHolder, int row, int column){ + setSelectedCellPositions(row, column); } - private void unselectedCellView() { - int unSelectedColor = mTableView.getUnSelectedColor(); - - // Change background color of the row header which is located on Y Position of the cell - // view. - AbstractViewHolder rowHeader = (AbstractViewHolder) mRowHeaderRecyclerView - .findViewHolderForAdapterPosition(mSelectedRowPosition); - - // If view is null, that means the row view holder was already recycled. - if (rowHeader != null) { - // Change color - rowHeader.setBackgroundColor(unSelectedColor); - // Change state - rowHeader.setSelected(SelectionState.UNSELECTED); - } - - // Change background color of the column header which is located on X Position of the cell - // view. - AbstractViewHolder columnHeader = (AbstractViewHolder) mColumnHeaderRecyclerView - .findViewHolderForAdapterPosition(mSelectedColumnPosition); - - if (columnHeader != null) { - // Change color - columnHeader.setBackgroundColor(unSelectedColor); - // Change state - columnHeader.setSelected(SelectionState.UNSELECTED); - } - } - - private void selectedColumnHeader() { - changeVisibleCellViewsBackgroundForColumn(mSelectedColumnPosition, true); - - changeSelectionOfRecyclerView(mRowHeaderRecyclerView, SelectionState.SHADOWED, mTableView - .getShadowColor()); + public boolean isCellSelected(int column, int row) { + return isColumnSelected(column) && isRowSelected(row); } - private void unselectedColumnHeader() { - changeVisibleCellViewsBackgroundForColumn(mSelectedColumnPosition, false); - - changeSelectionOfRecyclerView(mRowHeaderRecyclerView, SelectionState.UNSELECTED, - mTableView.getUnSelectedColor()); + public boolean isRowSelected(int column) { + return rowHasItemSelected(column); } - public boolean isCellSelected(int column, int row) { - return (getSelectedColumnPosition() == column && getSelectedRowPosition() == row) || - isColumnSelected(column) || isRowSelected(row); + public boolean isColumnSelected(int column) { + return columnHasItemSelected(column); } @NonNull @@ -251,20 +113,12 @@ public SelectionState getCellSelectionState(int column, int row) { return SelectionState.UNSELECTED; } - public boolean isColumnSelected(int column) { - return (getSelectedColumnPosition() == column && getSelectedRowPosition() == - UNSELECTED_POSITION); - } - public boolean isColumnShadowed(int column) { - return (getSelectedColumnPosition() == column && getSelectedRowPosition() != - UNSELECTED_POSITION) || (getSelectedColumnPosition() == UNSELECTED_POSITION && - getSelectedRowPosition() != UNSELECTED_POSITION); + return columnHasItemShadowed(column); } - public boolean isAnyColumnSelected() { - return (getSelectedColumnPosition() != SelectionHandler.UNSELECTED_POSITION && - getSelectedRowPosition() == SelectionHandler.UNSELECTED_POSITION); + public boolean isRowShadowed(int row) { + return rowHasItemShadowed(row); } @NonNull @@ -281,17 +135,6 @@ public SelectionState getColumnSelectionState(int column) { } } - public boolean isRowSelected(int row) { - return (getSelectedRowPosition() == row && getSelectedColumnPosition() == - UNSELECTED_POSITION); - } - - public boolean isRowShadowed(int row) { - return (getSelectedRowPosition() == row && getSelectedColumnPosition() != - UNSELECTED_POSITION) || (getSelectedRowPosition() == UNSELECTED_POSITION && - getSelectedColumnPosition() != UNSELECTED_POSITION); - } - @NonNull public SelectionState getRowSelectionState(int row) { @@ -355,32 +198,98 @@ private void changeVisibleCellViewsBackgroundForColumn(int column, boolean isSel } } - public void changeRowBackgroundColorBySelectionStatus(@NonNull AbstractViewHolder viewHolder, - @NonNull SelectionState selectionState) { - if (shadowEnabled && selectionState == SelectionState.SHADOWED) { - viewHolder.setBackgroundColor(mTableView.getShadowColor()); + public SelectionState getSelectionStateColumnHeader(int column) { + ISelectableModel columnModel = (ISelectableModel) mTableView.getAdapter().getColumnHeaderRecyclerViewAdapter().getItem(column); + return columnModel.getSelectionState(); + } - } else if (selectionState == SelectionState.SELECTED) { - viewHolder.setBackgroundColor(mTableView.getSelectedColor()); + private void setSelectionStateCell(int column, int row, SelectionState selectionState) { + ISelectableModel cellModel = (ISelectableModel) mTableView.getAdapter().getCellRecyclerViewAdapter().getItem(row, column); + cellModel.setSelectionState(selectionState); + } - } else { - viewHolder.setBackgroundColor(mTableView.getUnSelectedColor()); + private void setSelectionStateRowHeader(int row, SelectionState selectionState) { + ISelectableModel rowModel = (ISelectableModel) mTableView.getAdapter().getRowHeaderRecyclerViewAdapter().getItem(row); + rowModel.setSelectionState(selectionState); + } + + private void setSelectionStateColumnHeader(int column, SelectionState selectionState) { + ISelectableModel columnModel = (ISelectableModel) mTableView.getAdapter().getColumnHeaderRecyclerViewAdapter().getItem(column); + columnModel.setSelectionState(selectionState); + } + + public boolean columnHasItemSelected(int column) { + for (Object cell : mTableView.getAdapter().getCellRecyclerViewAdapter().getColumnItems(column)) { + if (cell instanceof ISelectableModel) { + if (((ISelectableModel) cell).getSelectionState() == SelectionState.SELECTED) { + return true; + } + } } + return false; } - public void changeColumnBackgroundColorBySelectionStatus(@NonNull AbstractViewHolder viewHolder, - @NonNull SelectionState selectionState) { - if (shadowEnabled && selectionState == SelectionState.SHADOWED) { - viewHolder.setBackgroundColor(mTableView.getShadowColor()); + public boolean rowHasItemSelected(int row) { + for (Object cell : mTableView.getAdapter().getCellRecyclerViewAdapter().getRowItems(row)) { + if (cell instanceof ISelectableModel) { + if (((ISelectableModel) cell).getSelectionState() == SelectionState.SELECTED) { + return true; + } + } + } + return false; + } - } else if (selectionState == SelectionState.SELECTED) { - viewHolder.setBackgroundColor(mTableView.getSelectedColor()); + public boolean columnHasItemShadowed(int column) { + for (Object cell : mTableView.getAdapter().getCellRecyclerViewAdapter().getColumnItems(column)) { + if (cell instanceof ISelectableModel) { + if (((ISelectableModel) cell).getSelectionState() == SelectionState.SHADOWED) { + return true; + } + } + } + return false; + } - } else { - viewHolder.setBackgroundColor(mTableView.getUnSelectedColor()); + public boolean rowHasItemShadowed(int row) { + for (Object cell : mTableView.getAdapter().getCellRecyclerViewAdapter().getRowItems(row)) { + if (cell instanceof ISelectableModel) { + if (((ISelectableModel) cell).getSelectionState() == SelectionState.SHADOWED) { + return true; + } + } + } + return false; + } + + public boolean isAnyColumnSelected(){ + for( int i=0; i < mTableView.getAdapter().getCellRecyclerViewAdapter().getItemCount()-1; i++) { + if(columnHasItemSelected(i)){ + return true; + } + } + return false; + } + + + public void changeRowBackgroundColorBySelectionStatus(@NonNull AbstractViewHolder viewHolder, + @NonNull SelectionState selectionState) { + if (shadowEnabled || (!shadowEnabled && selectionState != SelectionState.SHADOWED)) { + viewHolder.setBackgroundColor(mTableView.getAdapter().getColorForSelection(selectionState)); } } + public void changeColumnBackgroundColorBySelectionStatus(@NonNull AbstractViewHolder viewHolder, + @NonNull SelectionState selectionState) { + if (shadowEnabled || (!shadowEnabled && selectionState != SelectionState.SHADOWED)) { + viewHolder.setBackgroundColor(mTableView.getAdapter().getColorForSelection(selectionState)); + } + } + + public boolean isMultiSelectionEnabled() { + return mMultiSelectionEnabled; + } + public void changeSelectionOfRecyclerView(CellRecyclerView recyclerView, @NonNull AbstractViewHolder .SelectionState selectionState, @ColorInt int backgroundColor) { @@ -405,18 +314,218 @@ public void changeSelectionOfRecyclerView(CellRecyclerView recyclerView, @NonNul } } - public void clearSelection() { - unselectedRowHeader(); - unselectedCellView(); - unselectedColumnHeader(); + public void setMultiSelectionEnabled(boolean enabled) { + this.mMultiSelectionEnabled = enabled; } - public void setSelectedRowPosition(int row) { - this.mSelectedRowPosition = row; + + /** + * set selected state for one cell at (row, column) coordinates + * notify can be set to true to notify adapter. However, is you + * consider doing multiple operations, you might notify the adapter + * manually. + * + * @param column + * @param row + * @param notify + */ + private void setSelectedCellPositions(int row, int column, boolean notify) { + boolean clean = false; + if (selectionType != SELECTION_TYPE.CELLS && selectionType != SELECTION_TYPE.NONE) { + // unselect everything + clearAllSelection(true); + clean = true; + } + selectionType = SELECTION_TYPE.CELLS; + + if (!mMultiSelectionEnabled && !clean) { + // unselect everything first + clearAllSelection(false); + } + + + if (getSelectionStateCell(column, row) != SelectionState.SELECTED) { + // Select the Cell + setSelectionStateCell(column, row, SelectionState.SELECTED); + + // Shadow column and row + if (shadowEnabled) { + setSelectionStateRowHeader(row, SelectionState.SHADOWED); + setSelectionStateColumnHeader(column, SelectionState.SHADOWED); + } + } else { + setSelectionStateCell(column, row, SelectionState.UNSELECTED); + + // unShadow column and row + // check if any other cell selection is shadowing the row (in case of multiselection) + if (!mMultiSelectionEnabled || !rowHasItemSelected(row)) { + setSelectionStateRowHeader(row, SelectionState.UNSELECTED); + } + + // check if any other cell selection is shadowing the column (in case of multiselection) + if (!mMultiSelectionEnabled || !columnHasItemSelected(column)) { + setSelectionStateColumnHeader(column, SelectionState.UNSELECTED); + } + } + + if (notify) { + mTableView.getAdapter().notifyDataSetChanged(); + } } - public void setSelectedColumnPosition(int column) { - this.mSelectedColumnPosition = column; + /** + * Select the full row + * + * @param rowPosition + */ + public void setSelectedRowPosition(int rowPosition) { + boolean clean = false; + if (selectionType != SELECTION_TYPE.ROWS && selectionType != SELECTION_TYPE.NONE) { + // unselect everything + clearAllSelection(true); + clean = true; + } + selectionType = SELECTION_TYPE.ROWS; + + if (!mMultiSelectionEnabled && !clean) { + // unselect everything first + clearAllSelection(false); + } + + + for (Object cell : mTableView.getAdapter().getCellRecyclerViewAdapter().getRowItems(rowPosition)) { + if (cell instanceof ISelectableModel) { + ISelectableModel selectableModel = (ISelectableModel) cell; + if (selectableModel.getSelectionState() != AbstractViewHolder.SelectionState.SELECTED) { + selectableModel.setSelectionState(AbstractViewHolder.SelectionState.SELECTED); + } else { + selectableModel.setSelectionState(AbstractViewHolder.SelectionState.UNSELECTED); + } + } + } + + Object rowHeader = mTableView.getAdapter().getRowHeaderRecyclerViewAdapter().getItem(rowPosition); + if (rowHeader instanceof ISelectableModel) { + ISelectableModel selectableModel = (ISelectableModel) rowHeader; + if (selectableModel.getSelectionState() != AbstractViewHolder.SelectionState.SELECTED) { + selectableModel.setSelectionState(AbstractViewHolder.SelectionState.SELECTED); + } else { + selectableModel.setSelectionState(AbstractViewHolder.SelectionState.UNSELECTED); + } + } + + + if (shadowEnabled) { + // Shadow/UnShadow row headers + for (int columnPosition = 0; columnPosition < mTableView.getAdapter().getColumnHeaderRecyclerViewAdapter().getItemCount(); columnPosition++) { + if (getSelectionStateRowHeader(columnPosition) != SelectionState.SHADOWED) { + setSelectionStateColumnHeader(columnPosition, SelectionState.SHADOWED); + } else { + setSelectionStateColumnHeader(columnPosition, SelectionState.UNSELECTED); + } + } + } + + mTableView.getAdapter().notifyDataSetChanged(); + } + + /** + * Select the full column + * + * @param columnPosition + */ + public void setSelectedColumnPosition(Integer columnPosition) { + boolean clean = false; + if (selectionType != SELECTION_TYPE.COLUMNS && selectionType != SELECTION_TYPE.NONE) { + // unselect everything + clearAllSelection(true); + clean = true; + } + selectionType = SELECTION_TYPE.COLUMNS; + + + if (!mMultiSelectionEnabled && !clean) { + // unselect everything first + clearAllSelection(false); + } + + for (Object cell : mTableView.getAdapter().getCellRecyclerViewAdapter().getColumnItems(columnPosition)) { + if (cell instanceof ISelectableModel) { + ISelectableModel selectableModel = (ISelectableModel) cell; + if (selectableModel.getSelectionState() != AbstractViewHolder.SelectionState.SELECTED) { + selectableModel.setSelectionState(AbstractViewHolder.SelectionState.SELECTED); + } else { + selectableModel.setSelectionState(AbstractViewHolder.SelectionState.UNSELECTED); + } + } + } + + + Object columnHeader = mTableView.getAdapter().getColumnHeaderRecyclerViewAdapter().getItem(columnPosition); + if (columnHeader instanceof ISelectableModel) { + ISelectableModel selectableModel = (ISelectableModel) columnHeader; + if (selectableModel.getSelectionState() != AbstractViewHolder.SelectionState.SELECTED) { + selectableModel.setSelectionState(AbstractViewHolder.SelectionState.SELECTED); + } else { + selectableModel.setSelectionState(AbstractViewHolder.SelectionState.UNSELECTED); + } + } + + if (shadowEnabled) { + // Shadow/UnShadow row headers + + for (int rowPosition = 0; rowPosition < mTableView.getAdapter().getRowHeaderRecyclerViewAdapter().getItemCount(); rowPosition++) { + if (getSelectionStateRowHeader(rowPosition) != SelectionState.SHADOWED) { + setSelectionStateRowHeader(rowPosition, SelectionState.SHADOWED); + } else { + setSelectionStateRowHeader(rowPosition, SelectionState.UNSELECTED); + } + } + } + + mTableView.getAdapter().notifyDataSetChanged(); + + } + + /** + * clear all selection + * + * @param notify + */ + public void clearAllSelection(boolean notify) { + + // clear cells + for (int rowPosition = 0; rowPosition < mTableView.getAdapter().getRowHeaderItemCount(); rowPosition++) { + // clear row headers + setSelectionStateRowHeader(rowPosition, AbstractViewHolder.SelectionState.UNSELECTED); + if (mTableView.getAdapter().getCellRowItems(rowPosition) != null) { + for (Object cell : mTableView.getAdapter().getCellRowItems(rowPosition)) { + if (cell instanceof ISelectableModel) { + ISelectableModel selectableModel = (ISelectableModel) cell; + selectableModel.setSelectionState(AbstractViewHolder.SelectionState.UNSELECTED); + } + } + } + } + + // clear column headers + for (int columnPosition = 0; columnPosition < mTableView.getAdapter().getColumnHeaderItemCount(); columnPosition++) { + setSelectionStateColumnHeader(columnPosition, AbstractViewHolder.SelectionState.UNSELECTED); + } + + if (notify) { + mTableView.getAdapter().notifyDataSetChanged(); + } + } + public SelectionState getSelectionStateCell(int column, int row) { + ISelectableModel cellModel = (ISelectableModel) mTableView.getAdapter().getCellRecyclerViewAdapter().getItem(row, column); + return cellModel.getSelectionState(); + } + + public SelectionState getSelectionStateRowHeader(int row) { + ISelectableModel rowModel = (ISelectableModel) mTableView.getAdapter().getRowHeaderRecyclerViewAdapter().getItem(row); + return rowModel.getSelectionState(); + } } diff --git a/tableview/src/main/java/com/evrencoskun/tableview/listener/itemclick/CellRecyclerViewItemClickListener.java b/tableview/src/main/java/com/evrencoskun/tableview/listener/itemclick/CellRecyclerViewItemClickListener.java index 56bb71a0..13659311 100644 --- a/tableview/src/main/java/com/evrencoskun/tableview/listener/itemclick/CellRecyclerViewItemClickListener.java +++ b/tableview/src/main/java/com/evrencoskun/tableview/listener/itemclick/CellRecyclerViewItemClickListener.java @@ -59,12 +59,12 @@ protected boolean clickAction(@NonNull RecyclerView view, @NonNull MotionEvent e int row = adapter.getYPosition(); // Control to ignore selection color - if (!mTableView.isIgnoreSelectionColors()) { - mSelectionHandler.setSelectedCellPositions(holder, column, row); + if (!mTableView.isIgnoreSelectionColors() && mTableView.isSelectable()) { + mSelectionHandler.setSelectedCellPositions(row, column); } // Call ITableView listener for item click - getTableViewListener().onCellClicked(holder, column, row); + getTableViewListener().onCellClicked(holder, row, column); return true; } diff --git a/tableview/src/main/java/com/evrencoskun/tableview/listener/itemclick/ColumnHeaderRecyclerViewItemClickListener.java b/tableview/src/main/java/com/evrencoskun/tableview/listener/itemclick/ColumnHeaderRecyclerViewItemClickListener.java index 5f845bf0..7935c7ce 100644 --- a/tableview/src/main/java/com/evrencoskun/tableview/listener/itemclick/ColumnHeaderRecyclerViewItemClickListener.java +++ b/tableview/src/main/java/com/evrencoskun/tableview/listener/itemclick/ColumnHeaderRecyclerViewItemClickListener.java @@ -52,8 +52,8 @@ protected boolean clickAction(@NonNull RecyclerView view, @NonNull MotionEvent e int column = holder.getAdapterPosition(); // Control to ignore selection color - if (!mTableView.isIgnoreSelectionColors()) { - mSelectionHandler.setSelectedColumnPosition(holder, column); + if (!mTableView.isIgnoreSelectionColors() && mTableView.isSelectable()) { + mSelectionHandler.setSelectedColumnPosition(column); } // Call ITableView listener for item click diff --git a/tableview/src/main/java/com/evrencoskun/tableview/listener/itemclick/RowHeaderRecyclerViewItemClickListener.java b/tableview/src/main/java/com/evrencoskun/tableview/listener/itemclick/RowHeaderRecyclerViewItemClickListener.java index 7435d279..1e6a3f8c 100644 --- a/tableview/src/main/java/com/evrencoskun/tableview/listener/itemclick/RowHeaderRecyclerViewItemClickListener.java +++ b/tableview/src/main/java/com/evrencoskun/tableview/listener/itemclick/RowHeaderRecyclerViewItemClickListener.java @@ -51,8 +51,8 @@ protected boolean clickAction(@NonNull RecyclerView view, @NonNull MotionEvent e int row = holder.getAdapterPosition(); // Control to ignore selection color - if (!mTableView.isIgnoreSelectionColors()) { - mSelectionHandler.setSelectedRowPosition(holder, row); + if (!mTableView.isIgnoreSelectionColors() && mTableView.isSelectable()) { + mSelectionHandler.setSelectedRowPosition(row); } // Call ITableView listener for item click