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;
18 
19 import static android.view.View.GONE;
20 import static android.view.View.VISIBLE;
21 import static com.android.documentsui.Shared.DEBUG;
22 
23 import android.annotation.Nullable;
24 import android.graphics.drawable.Drawable;
25 import android.util.Log;
26 import android.view.LayoutInflater;
27 import android.view.View;
28 import android.view.ViewGroup;
29 import android.widget.AdapterView;
30 import android.widget.AdapterView.OnItemSelectedListener;
31 import android.widget.BaseAdapter;
32 import android.widget.Spinner;
33 import android.widget.TextView;
34 
35 import com.android.documentsui.dirlist.AnimationView;
36 import com.android.documentsui.model.DocumentInfo;
37 import com.android.documentsui.model.RootInfo;
38 
39 /**
40  * A facade over the portions of the app and drawer toolbars.
41  */
42 class NavigationView {
43 
44     private static final String TAG = "NavigationView";
45 
46     private final DrawerController mDrawer;
47     private final DocumentsToolbar mToolbar;
48     private final Spinner mBreadcrumb;
49     private final State mState;
50     private final NavigationView.Environment mEnv;
51     private final BreadcrumbAdapter mBreadcrumbAdapter;
52 
53     private boolean mIgnoreNextNavigation;
54 
NavigationView( DrawerController drawer, DocumentsToolbar toolbar, Spinner breadcrumb, State state, NavigationView.Environment env)55     public NavigationView(
56             DrawerController drawer,
57             DocumentsToolbar toolbar,
58             Spinner breadcrumb,
59             State state,
60             NavigationView.Environment env) {
61 
62         mToolbar = toolbar;
63         mBreadcrumb = breadcrumb;
64         mDrawer = drawer;
65         mState = state;
66         mEnv = env;
67 
68         mBreadcrumbAdapter = new BreadcrumbAdapter(mState, mEnv);
69         mToolbar.setNavigationOnClickListener(
70                 new View.OnClickListener() {
71                     @Override
72                     public void onClick(View v) {
73                         onNavigationIconClicked();
74                     }
75 
76                 });
77 
78         mBreadcrumb.setOnItemSelectedListener(
79                 new OnItemSelectedListener() {
80                     @Override
81                     public void onItemSelected(
82                             AdapterView<?> parent, View view, int position, long id) {
83                         onBreadcrumbItemSelected(position);
84                     }
85 
86                     @Override
87                     public void onNothingSelected(AdapterView<?> parent) {}
88                 });
89 
90     }
91 
onNavigationIconClicked()92     private void onNavigationIconClicked() {
93         if (mDrawer.isPresent()) {
94             mDrawer.setOpen(true, DrawerController.OPENED_HAMBURGER);
95         }
96     }
97 
onBreadcrumbItemSelected(int position)98     private void onBreadcrumbItemSelected(int position) {
99         if (mIgnoreNextNavigation) {
100             mIgnoreNextNavigation = false;
101             return;
102         }
103 
104         while (mState.stack.size() > position + 1) {
105             mState.popDocument();
106         }
107         mEnv.refreshCurrentRootAndDirectory(AnimationView.ANIM_LEAVE);
108     }
109 
update()110     void update() {
111 
112         // TODO: Looks to me like this block is never getting hit.
113         if (mEnv.isSearchExpanded()) {
114             mToolbar.setTitle(null);
115             mBreadcrumb.setVisibility(View.GONE);
116             mBreadcrumb.setAdapter(null);
117             return;
118         }
119 
120         mDrawer.setTitle(mEnv.getDrawerTitle());
121 
122         mToolbar.setNavigationIcon(getActionBarIcon());
123         mToolbar.setNavigationContentDescription(R.string.drawer_open);
124 
125         if (mState.stack.size() <= 1) {
126             showBreadcrumb(false);
127             String title = mEnv.getCurrentRoot().title;
128             if (DEBUG) Log.d(TAG, "New toolbar title is: " + title);
129             mToolbar.setTitle(title);
130         } else {
131             showBreadcrumb(true);
132             mToolbar.setTitle(null);
133             mIgnoreNextNavigation = true;
134             mBreadcrumb.setSelection(mBreadcrumbAdapter.getCount() - 1, false);
135         }
136 
137         if (DEBUG) Log.d(TAG, "Final toolbar title is: " + mToolbar.getTitle());
138     }
139 
showBreadcrumb(boolean visibility)140     private void showBreadcrumb(boolean visibility) {
141         if (visibility) {
142             mBreadcrumb.setVisibility(VISIBLE);
143             mBreadcrumb.setAdapter(mBreadcrumbAdapter);
144         } else {
145             mBreadcrumb.setVisibility(GONE);
146             mBreadcrumb.setAdapter(null);
147         }
148     }
149 
150     // Hamburger if drawer is present, else sad nullness.
getActionBarIcon()151     private @Nullable Drawable getActionBarIcon() {
152         if (mDrawer.isPresent()) {
153             return mToolbar.getContext().getDrawable(R.drawable.ic_hamburger);
154         } else {
155             return null;
156         }
157     }
158 
revealRootsDrawer(boolean open)159     void revealRootsDrawer(boolean open) {
160         mDrawer.setOpen(open);
161     }
162 
163     /**
164      * Class providing toolbar with runtime access to useful activity data.
165      */
166     static final class BreadcrumbAdapter extends BaseAdapter {
167 
168         private Environment mEnv;
169         private State mState;
170 
BreadcrumbAdapter(State state, Environment env)171         public BreadcrumbAdapter(State state, Environment env) {
172             mState = state;
173             mEnv = env;
174         }
175 
176         @Override
getCount()177         public int getCount() {
178             return mState.stack.size();
179         }
180 
181         @Override
getItem(int position)182         public DocumentInfo getItem(int position) {
183             return mState.stack.get(mState.stack.size() - position - 1);
184         }
185 
186         @Override
getItemId(int position)187         public long getItemId(int position) {
188             return position;
189         }
190 
191         @Override
getView(int position, View convertView, ViewGroup parent)192         public View getView(int position, View convertView, ViewGroup parent) {
193             if (convertView == null) {
194                 convertView = LayoutInflater.from(parent.getContext())
195                         .inflate(R.layout.item_subdir_title, parent, false);
196             }
197 
198             final TextView title = (TextView) convertView.findViewById(android.R.id.title);
199             final DocumentInfo doc = getItem(position);
200 
201             if (position == 0) {
202                 final RootInfo root = mEnv.getCurrentRoot();
203                 title.setText(root.title);
204             } else {
205                 title.setText(doc.displayName);
206             }
207 
208             return convertView;
209         }
210 
211         @Override
getDropDownView(int position, View convertView, ViewGroup parent)212         public View getDropDownView(int position, View convertView, ViewGroup parent) {
213             if (convertView == null) {
214                 convertView = LayoutInflater.from(parent.getContext())
215                         .inflate(R.layout.item_subdir, parent, false);
216             }
217 
218             final TextView title = (TextView) convertView.findViewById(android.R.id.title);
219             final DocumentInfo doc = getItem(position);
220 
221             if (position == 0) {
222                 final RootInfo root = mEnv.getCurrentRoot();
223                 title.setText(root.title);
224             } else {
225                 title.setText(doc.displayName);
226             }
227 
228             return convertView;
229         }
230     }
231 
232     interface Environment {
getCurrentRoot()233         RootInfo getCurrentRoot();
getDrawerTitle()234         String getDrawerTitle();
refreshCurrentRootAndDirectory(int animation)235         void refreshCurrentRootAndDirectory(int animation);
isSearchExpanded()236         boolean isSearchExpanded();
237     }
238 }
239