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