Home | History | Annotate | Download | only in sorting
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.documentsui.sorting;
     18 
     19 import android.annotation.StringRes;
     20 import android.view.Gravity;
     21 import android.view.Menu;
     22 import android.view.MenuItem;
     23 import android.view.View;
     24 import android.widget.ImageView;
     25 import android.widget.PopupMenu;
     26 import android.widget.TextView;
     27 
     28 import com.android.documentsui.R;
     29 import com.android.documentsui.sorting.SortController.WidgetController;
     30 import com.android.documentsui.sorting.SortDimension.SortDirection;
     31 import com.android.documentsui.sorting.SortModel.SortDimensionId;
     32 import com.android.documentsui.sorting.SortModel.UpdateType;
     33 
     34 /**
     35  * View controller for the sort widget in grid mode and in small screens.
     36  */
     37 public final class DropdownSortWidgetController implements WidgetController {
     38 
     39     private static final int LEVEL_UPWARD = 0;
     40     private static final int LEVEL_DOWNWARD = 10000;
     41 
     42     private final SortModel mModel;
     43     private final View mWidget;
     44     private final TextView mDimensionButton;
     45     private final PopupMenu mMenu;
     46     private final ImageView mArrow;
     47     private final SortModel.UpdateListener mListener;
     48 
     49     public DropdownSortWidgetController(SortModel model, View widget) {
     50         mModel = model;
     51         mWidget = widget;
     52 
     53         mDimensionButton = (TextView) mWidget.findViewById(R.id.sort_dimen_dropdown);
     54         mDimensionButton.setOnClickListener(this::showMenu);
     55 
     56         mMenu = new PopupMenu(widget.getContext(), mDimensionButton, Gravity.END | Gravity.TOP);
     57         mMenu.setOnMenuItemClickListener(this::onSelectDimension);
     58 
     59         mArrow = (ImageView) mWidget.findViewById(R.id.sort_arrow);
     60         mArrow.setOnClickListener(this::onChangeDirection);
     61 
     62         populateMenuItems();
     63         onModelUpdate(mModel, SortModel.UPDATE_TYPE_UNSPECIFIED);
     64 
     65         mListener = this::onModelUpdate;
     66         mModel.addListener(mListener);
     67     }
     68 
     69     @Override
     70     public void setVisibility(int visibility) {
     71         mWidget.setVisibility(visibility);
     72     }
     73 
     74     @Override
     75     public void destroy() {
     76         mModel.removeListener(mListener);
     77     }
     78 
     79     private void populateMenuItems() {
     80         Menu menu = mMenu.getMenu();
     81         menu.clear();
     82         for (int i = 0; i < mModel.getSize(); ++i) {
     83             SortDimension dimension = mModel.getDimensionAt(i);
     84             if (dimension.getSortCapability() != SortDimension.SORT_CAPABILITY_NONE) {
     85                 menu.add(0, dimension.getId(), Menu.NONE, dimension.getLabelId());
     86             }
     87         }
     88     }
     89 
     90     private void showMenu(View v) {
     91         mMenu.show();
     92     }
     93 
     94     private void onModelUpdate(SortModel model, @UpdateType int updateType) {
     95         final @SortDimensionId int sortedId = model.getSortedDimensionId();
     96 
     97         if ((updateType & SortModel.UPDATE_TYPE_VISIBILITY) != 0) {
     98             updateVisibility();
     99         }
    100 
    101         if ((updateType & SortModel.UPDATE_TYPE_SORTING) != 0) {
    102             bindSortedDimension(sortedId);
    103             bindSortDirection(sortedId);
    104         }
    105     }
    106 
    107     private void updateVisibility() {
    108         Menu menu = mMenu.getMenu();
    109 
    110         for (int i = 0; i < menu.size(); ++i) {
    111             MenuItem item = menu.getItem(i);
    112             SortDimension dimension = mModel.getDimensionById(item.getItemId());
    113             item.setVisible(dimension.getVisibility() == View.VISIBLE);
    114         }
    115     }
    116 
    117     private void bindSortedDimension(@SortDimensionId int sortedId) {
    118         if (sortedId == SortModel.SORT_DIMENSION_ID_UNKNOWN) {
    119             mDimensionButton.setText(R.string.not_sorted);
    120         } else {
    121             SortDimension dimension = mModel.getDimensionById(sortedId);
    122             mDimensionButton.setText(dimension.getLabelId());
    123         }
    124     }
    125 
    126     private void bindSortDirection(@SortDimensionId int sortedId) {
    127         if (sortedId == SortModel.SORT_DIMENSION_ID_UNKNOWN) {
    128             mArrow.setVisibility(View.INVISIBLE);
    129         } else {
    130             final SortDimension dimension = mModel.getDimensionById(sortedId);
    131             switch (dimension.getSortDirection()) {
    132                 case SortDimension.SORT_DIRECTION_NONE:
    133                     mArrow.setVisibility(View.INVISIBLE);
    134                     break;
    135                 case SortDimension.SORT_DIRECTION_ASCENDING:
    136                     showArrow(LEVEL_UPWARD, R.string.sort_direction_ascending);
    137                     break;
    138                 case SortDimension.SORT_DIRECTION_DESCENDING:
    139                     showArrow(LEVEL_DOWNWARD, R.string.sort_direction_descending);
    140                     break;
    141                 default:
    142                     throw new IllegalStateException(
    143                             "Unknown sort direction: " + dimension.getSortDirection() + ".");
    144             }
    145         }
    146     }
    147 
    148     private void showArrow(int level, @StringRes int descriptionId) {
    149         mArrow.setVisibility(View.VISIBLE);
    150 
    151         mArrow.getDrawable().mutate();
    152         mArrow.setImageLevel(level);
    153         mArrow.setContentDescription(mArrow.getContext().getString(descriptionId));
    154     }
    155 
    156     private boolean onSelectDimension(MenuItem item) {
    157         final @SortDirection int preferredDirection = mModel.getCurrentSortDirection();
    158 
    159         final SortDimension dimension = mModel.getDimensionById(item.getItemId());
    160         final @SortDirection int direction;
    161         if ((dimension.getSortCapability() & preferredDirection) > 0) {
    162             direction = preferredDirection;
    163         } else {
    164             direction = dimension.getDefaultSortDirection();
    165         }
    166 
    167         mModel.sortByUser(dimension.getId(), direction);
    168 
    169         return true;
    170     }
    171 
    172     private void onChangeDirection(View v) {
    173         final @SortDimensionId int id = mModel.getSortedDimensionId();
    174         assert(id != SortModel.SORT_DIMENSION_ID_UNKNOWN);
    175 
    176         final SortDimension dimension = mModel.getDimensionById(id);
    177         mModel.sortByUser(dimension.getId(), dimension.getNextDirection());
    178     }
    179 }
    180