/* * Copyright (C) 2012 The CyanogenMod Project * * 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 com.cyanogenmod.filemanager.ui.widgets; import android.content.Context; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.HorizontalScrollView; import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.RelativeLayout; import com.cyanogenmod.filemanager.R; import com.cyanogenmod.filemanager.model.DiskUsage; import com.cyanogenmod.filemanager.model.MountPoint; import com.cyanogenmod.filemanager.tasks.FilesystemAsyncTask; import com.cyanogenmod.filemanager.ui.ThemeManager; import com.cyanogenmod.filemanager.ui.ThemeManager.Theme; import com.cyanogenmod.filemanager.util.FileHelper; import com.cyanogenmod.filemanager.util.StorageHelper; import java.io.File; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * A view that holds a navigation breadcrumb pattern. */ public class BreadcrumbView extends RelativeLayout implements Breadcrumb, OnClickListener { /** * @hide */ HorizontalScrollView mScrollView; private ViewGroup mBreadcrumbBar; /** * @hide */ ImageView mFilesystemInfo; /** * @hide */ ProgressBar mDiskUsageInfo; /** * @hide */ View mLoading; private FilesystemAsyncTask mFilesystemAsyncTask; private int mFreeDiskSpaceWarningLevel = 95; private List<BreadcrumbListener> mBreadcrumbListeners; private String mCurrentPath; /** * Constructor of <code>BreadcrumbView</code>. * * @param context The current context */ public BreadcrumbView(Context context) { super(context); init(); } /** * Constructor of <code>BreadcrumbView</code>. * * @param context The current context * @param attrs The attributes of the XML tag that is inflating the view. */ public BreadcrumbView(Context context, AttributeSet attrs) { super(context, attrs); init(); } /** * Constructor of <code>BreadcrumbView</code>. * * @param context The current context * @param attrs The attributes of the XML tag that is inflating the view. * @param defStyle The default style to apply to this view. If 0, no style * will be applied (beyond what is included in the theme). This may * either be an attribute resource, whose value will be retrieved * from the current theme, or an explicit style resource. */ public BreadcrumbView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(); } /** * Method that initializes the view. This method loads all the necessary * information and create an appropriate layout for the view */ private void init() { //Initialize the listeners this.mBreadcrumbListeners = Collections.synchronizedList(new ArrayList<BreadcrumbListener>()); //Add the view of the breadcrumb addView(inflate(getContext(), R.layout.breadcrumb_view, null)); //Recovery all views this.mScrollView = (HorizontalScrollView)findViewById(R.id.breadcrumb_scrollview); this.mBreadcrumbBar = (ViewGroup)findViewById(R.id.breadcrumb); this.mFilesystemInfo = (ImageView)findViewById(R.id.ab_filesystem_info); this.mDiskUsageInfo = (ProgressBar)findViewById(R.id.breadcrumb_diskusage); this.mLoading = findViewById(R.id.breadcrumb_loading); // Change the image of filesystem (this is not called after a changeBreadcrumbPath call, // so if need to be theme previously to protect from errors) Theme theme = ThemeManager.getCurrentTheme(getContext()); theme.setImageDrawable( getContext(), this.mFilesystemInfo, "filesystem_warning_drawable"); //$NON-NLS-1$ } /** * {@inheritDoc} */ @Override public void setFreeDiskSpaceWarningLevel(int percentage) { this.mFreeDiskSpaceWarningLevel = percentage; } /** * {@inheritDoc} */ @Override public void addBreadcrumbListener(BreadcrumbListener listener) { this.mBreadcrumbListeners.add(listener); } /** * {@inheritDoc} */ @Override public void removeBreadcrumbListener(BreadcrumbListener listener) { this.mBreadcrumbListeners.remove(listener); } /** * {@inheritDoc} */ @Override public void startLoading() { //Show/Hide views this.post(new Runnable() { @Override public void run() { BreadcrumbView.this.mFilesystemInfo.setVisibility(View.INVISIBLE); BreadcrumbView.this.mDiskUsageInfo.setVisibility(View.INVISIBLE); BreadcrumbView.this.mLoading.setVisibility(View.VISIBLE); } }); } /** * {@inheritDoc} */ @Override public void endLoading() { //Show/Hide views this.post(new Runnable() { @Override public void run() { BreadcrumbView.this.mLoading.setVisibility(View.INVISIBLE); BreadcrumbView.this.mFilesystemInfo.setVisibility(View.VISIBLE); BreadcrumbView.this.mDiskUsageInfo.setVisibility(View.VISIBLE); } }); } /** * {@inheritDoc} */ @Override public void changeBreadcrumbPath(final String newPath, final boolean chRooted) { //Sets the current path this.mCurrentPath = newPath; //Update the mount point information updateMountPointInfo(); //Remove all views this.mBreadcrumbBar.removeAllViews(); // The first is always the root (except if we are in a ChRooted environment) if (!chRooted) { this.mBreadcrumbBar.addView(createBreadcrumbItem(new File(FileHelper.ROOT_DIRECTORY))); } //Add the rest of the path String[] dirs = newPath.split(File.separator); int cc = dirs.length; if (chRooted) { boolean first = true; for (int i = 1; i < cc; i++) { File f = createFile(dirs, i); if (StorageHelper.isPathInStorageVolume(f.getAbsolutePath())) { if (!first) { this.mBreadcrumbBar.addView(createItemDivider()); } first = false; this.mBreadcrumbBar.addView(createBreadcrumbItem(f)); } } } else { for (int i = 1; i < cc; i++) { this.mBreadcrumbBar.addView(createItemDivider()); this.mBreadcrumbBar.addView(createBreadcrumbItem(createFile(dirs, i))); } } // Now apply the theme to the breadcrumb applyTheme(); //Set scrollbar at the end this.mScrollView.post(new Runnable() { @Override public void run() { BreadcrumbView.this.mScrollView.fullScroll(View.FOCUS_RIGHT); } }); } /** * {@inheritDoc} */ @Override public synchronized void updateMountPointInfo() { //Cancel the current execution (if any) and launch again if (this.mFilesystemAsyncTask != null && this.mFilesystemAsyncTask.isRunning()) { this.mFilesystemAsyncTask.cancel(true); } final ImageView filesystemInfo = (ImageView)findViewById(R.id.ab_filesystem_info); final ProgressBar diskUsageInfo = (ProgressBar)findViewById(R.id.breadcrumb_diskusage); this.mFilesystemAsyncTask = new FilesystemAsyncTask( getContext(), filesystemInfo, diskUsageInfo, this.mFreeDiskSpaceWarningLevel); this.mFilesystemAsyncTask.execute(this.mCurrentPath); } /** * Method that creates a new path divider. * * @return View The path divider */ private View createItemDivider() { LayoutInflater inflater = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); return inflater.inflate(R.layout.breadcrumb_item_divider, this.mBreadcrumbBar, false); } /** * Method that creates a new split path. * * @param dir The path * @return BreadcrumbItem The view create */ private BreadcrumbItem createBreadcrumbItem(File dir) { LayoutInflater inflater = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); BreadcrumbItem item = (BreadcrumbItem)inflater.inflate( R.layout.breadcrumb_item, this.mBreadcrumbBar, false); item.setText(dir.getName().length() != 0 ? dir.getName() : dir.getPath()); item.setItemPath(dir.getPath()); item.setOnClickListener(this); return item; } /** * Method that creates the a new file reference for a partial * breadcrumb item. * * @param dirs The split strings directory * @param pos The position up to which to create * @return File The file reference */ @SuppressWarnings("static-method") private File createFile(String[] dirs, int pos) { File parent = new File(FileHelper.ROOT_DIRECTORY); for (int i = 1; i < pos; i++) { parent = new File(parent, dirs[i]); } return new File(parent, dirs[pos]); } /** * {@inheritDoc} */ @Override public void onClick(View v) { BreadcrumbItem item = (BreadcrumbItem)v; int cc = this.mBreadcrumbListeners.size(); for (int i = 0; i < cc; i++) { this.mBreadcrumbListeners.get(i).onBreadcrumbItemClick(item); } } /** * {@inheritDoc} */ @Override public MountPoint getMountPointInfo() { if (this.mFilesystemInfo != null) { return (MountPoint)this.mFilesystemInfo.getTag(); } return null; } /** * {@inheritDoc} */ @Override public DiskUsage getDiskUsageInfo() { if (this.mDiskUsageInfo != null) { return (DiskUsage)this.mDiskUsageInfo.getTag(); } return null; } /** * {@inheritDoc} */ @Override public void applyTheme() { Theme theme = ThemeManager.getCurrentTheme(getContext()); //- Breadcrumb if (this.mBreadcrumbBar != null) { int cc = this.mBreadcrumbBar.getChildCount(); for (int i = 0; i < cc; i++) { // There are 2 types: Breadcrumb items and separators View v = this.mBreadcrumbBar.getChildAt(i); if (v instanceof BreadcrumbItem) { // Breadcrumb item theme.setTextColor( getContext(), (BreadcrumbItem)v, "text_color"); //$NON-NLS-1$ } else if (v instanceof ImageView) { // Divider drawable theme.setImageDrawable( getContext(), (ImageView)v, "breadcrumb_divider_drawable"); //$NON-NLS-1$ } } } if (this.mDiskUsageInfo != null) { Drawable dw = theme.getDrawable(getContext(), "horizontal_progress_bar"); //$NON-NLS-1$ this.mDiskUsageInfo.setProgressDrawable(dw); } } }