2 * Copyright (C) 2012 The CyanogenMod Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.cyanogenmod.filemanager.ui.widgets;
19 import android.app.Activity;
20 import android.content.Context;
21 import android.content.SharedPreferences;
22 import android.content.res.TypedArray;
23 import android.os.AsyncTask;
24 import android.os.storage.StorageVolume;
25 import android.util.AttributeSet;
26 import android.util.Log;
27 import android.view.View;
28 import android.widget.AdapterView;
29 import android.widget.ListAdapter;
30 import android.widget.RelativeLayout;
31 import android.widget.Toast;
33 import com.cyanogenmod.filemanager.FileManagerApplication;
34 import com.cyanogenmod.filemanager.R;
35 import com.cyanogenmod.filemanager.adapters.FileSystemObjectAdapter;
36 import com.cyanogenmod.filemanager.adapters.FileSystemObjectAdapter.OnSelectionChangedListener;
37 import com.cyanogenmod.filemanager.console.ConsoleAllocException;
38 import com.cyanogenmod.filemanager.listeners.OnHistoryListener;
39 import com.cyanogenmod.filemanager.listeners.OnRequestRefreshListener;
40 import com.cyanogenmod.filemanager.listeners.OnSelectionListener;
41 import com.cyanogenmod.filemanager.model.Directory;
42 import com.cyanogenmod.filemanager.model.FileSystemObject;
43 import com.cyanogenmod.filemanager.model.ParentDirectory;
44 import com.cyanogenmod.filemanager.model.Symlink;
45 import com.cyanogenmod.filemanager.parcelables.NavigationViewInfoParcelable;
46 import com.cyanogenmod.filemanager.parcelables.SearchInfoParcelable;
47 import com.cyanogenmod.filemanager.preferences.FileManagerSettings;
48 import com.cyanogenmod.filemanager.preferences.NavigationLayoutMode;
49 import com.cyanogenmod.filemanager.preferences.ObjectIdentifier;
50 import com.cyanogenmod.filemanager.preferences.Preferences;
51 import com.cyanogenmod.filemanager.ui.policy.IntentsActionPolicy;
52 import com.cyanogenmod.filemanager.util.CommandHelper;
53 import com.cyanogenmod.filemanager.util.DialogHelper;
54 import com.cyanogenmod.filemanager.util.ExceptionUtil;
55 import com.cyanogenmod.filemanager.util.FileHelper;
56 import com.cyanogenmod.filemanager.util.MimeTypeHelper;
57 import com.cyanogenmod.filemanager.util.StorageHelper;
59 import java.util.ArrayList;
60 import java.util.List;
63 * The file manager implementation view (contains the graphical representation and the input
64 * management for a file manager; shows the folders/files, the mode view, react touch events,
67 public class NavigationView extends RelativeLayout implements
68 AdapterView.OnItemClickListener, AdapterView.OnItemLongClickListener,
69 BreadcrumbListener, OnSelectionChangedListener, OnSelectionListener, OnRequestRefreshListener {
72 * An interface to communicate selection changes events.
74 public interface OnNavigationSelectionChangedListener {
76 * Method invoked when the selection changed.
78 * @param navView The navigation view that generate the event
79 * @param selectedItems The new selected items
81 void onSelectionChanged(NavigationView navView, List<FileSystemObject> selectedItems);
85 * An interface to communicate a request for show the menu associated
88 public interface OnNavigationRequestMenuListener {
90 * Method invoked when a request to show the menu associated
91 * with an item is started.
93 * @param navView The navigation view that generate the event
94 * @param item The item for which the request was started
96 void onRequestMenu(NavigationView navView, FileSystemObject item);
100 * An interface to communicate a request when the user choose a file.
102 public interface OnFilePickedListener {
104 * Method invoked when a request when the user choose a file.
106 * @param item The item choose
108 void onFilePicked(FileSystemObject item);
112 * The navigation view mode
115 public enum NAVIGATION_MODE {
117 * The navigation view acts as a browser, and allow open files itself.
121 * The navigation view acts as a picker of files
126 private static final String TAG = "NavigationView"; //$NON-NLS-1$
129 private String mCurrentDir;
130 private NavigationLayoutMode mCurrentMode;
134 List<FileSystemObject> mFiles;
135 private FileSystemObjectAdapter mAdapter;
137 private final Object mSync = new Object();
139 private OnHistoryListener mOnHistoryListener;
140 private OnNavigationSelectionChangedListener mOnNavigationSelectionChangedListener;
141 private OnNavigationRequestMenuListener mOnNavigationRequestMenuListener;
142 private OnFilePickedListener mOnFilePickedListener;
144 private boolean mChRooted;
146 private NAVIGATION_MODE mNavigationMode;
148 private String mMimeType = MimeTypeHelper.ALL_MIME_TYPES;
153 Breadcrumb mBreadcrumb;
157 NavigationCustomTitleView mTitle;
161 AdapterView<?> mAdapterView;
163 //The layout for icons mode
164 private static final int RESOURCE_MODE_ICONS_LAYOUT = R.layout.navigation_view_icons;
165 private static final int RESOURCE_MODE_ICONS_ITEM = R.layout.navigation_view_icons_item;
166 //The layout for simple mode
167 private static final int RESOURCE_MODE_SIMPLE_LAYOUT = R.layout.navigation_view_simple;
168 private static final int RESOURCE_MODE_SIMPLE_ITEM = R.layout.navigation_view_simple_item;
169 //The layout for details mode
170 private static final int RESOURCE_MODE_DETAILS_LAYOUT = R.layout.navigation_view_details;
171 private static final int RESOURCE_MODE_DETAILS_ITEM = R.layout.navigation_view_details_item;
173 //The current layout identifier (is shared for all the mode layout)
174 private static final int RESOURCE_CURRENT_LAYOUT = R.id.navigation_view_layout;
177 * Constructor of <code>NavigationView</code>.
179 * @param context The current context
180 * @param attrs The attributes of the XML tag that is inflating the view.
182 public NavigationView(Context context, AttributeSet attrs) {
183 super(context, attrs);
184 TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.Navigable);
193 * Constructor of <code>NavigationView</code>.
195 * @param context The current context
196 * @param attrs The attributes of the XML tag that is inflating the view.
197 * @param defStyle The default style to apply to this view. If 0, no style
198 * will be applied (beyond what is included in the theme). This may
199 * either be an attribute resource, whose value will be retrieved
200 * from the current theme, or an explicit style resource.
202 public NavigationView(Context context, AttributeSet attrs, int defStyle) {
203 super(context, attrs, defStyle);
204 TypedArray a = context.obtainStyledAttributes(
205 attrs, R.styleable.Navigable, defStyle, 0);
214 * Invoked when the instance need to be saved.
216 * @return NavigationViewInfoParcelable The serialized info
218 public NavigationViewInfoParcelable onSaveState() {
219 //Return the persistent the data
220 NavigationViewInfoParcelable parcel = new NavigationViewInfoParcelable();
221 parcel.setId(this.mId);
222 parcel.setCurrentDir(this.mCurrentDir);
223 parcel.setChRooted(this.mChRooted);
224 parcel.setSelectedFiles(this.mAdapter.getSelectedItems());
225 parcel.setFiles(this.mFiles);
230 * Invoked when the instance need to be restored.
232 * @param info The serialized info
234 public void onRestoreState(NavigationViewInfoParcelable info) {
236 this.mId = info.getId();
237 this.mCurrentDir = info.getCurrentDir();
238 this.mChRooted = info.getChRooted();
239 this.mFiles = info.getFiles();
240 this.mAdapter.setSelectedItems(info.getSelectedFiles());
247 * Method that initializes the view. This method loads all the necessary
248 * information and create an appropriate layout for the view.
250 * @param tarray The type array
252 private void init(TypedArray tarray) {
254 this.mNavigationMode = NAVIGATION_MODE.BROWSABLE;
255 int mode = tarray.getInteger(
256 R.styleable.Navigable_navigation,
257 NAVIGATION_MODE.BROWSABLE.ordinal());
258 if (mode >= 0 && mode < NAVIGATION_MODE.values().length) {
259 this.mNavigationMode = NAVIGATION_MODE.values()[mode];
262 //Initialize variables
263 this.mFiles = new ArrayList<FileSystemObject>();
265 // Is ChRooted environment?
266 if (this.mNavigationMode.compareTo(NAVIGATION_MODE.PICKABLE) == 0) {
267 // Pick mode is always ChRooted
268 this.mChRooted = true;
270 this.mChRooted = !FileManagerApplication.isAdvancedMode();
273 //Retrieve the default configuration
274 if (this.mNavigationMode.compareTo(NAVIGATION_MODE.BROWSABLE) == 0) {
275 SharedPreferences preferences = Preferences.getSharedPreferences();
276 int viewMode = preferences.getInt(
277 FileManagerSettings.SETTINGS_LAYOUT_MODE.getId(),
278 ((ObjectIdentifier)FileManagerSettings.
279 SETTINGS_LAYOUT_MODE.getDefaultValue()).getId());
280 changeViewMode(NavigationLayoutMode.fromId(viewMode));
282 // Pick mode has always a details layout
283 changeViewMode(NavigationLayoutMode.DETAILS);
288 * Method that returns the mime/type used by this class. Only the files with this mime/type
291 * @return String The mime/type
293 public String getMimeType() {
294 return this.mMimeType;
298 * Method that sets the mime/type used by this class. Only the files with this mime/type
301 * @param mimeType String The mime/type
303 public void setMimeType(String mimeType) {
304 this.mMimeType = mimeType;
308 * Method that returns the current file list of the navigation view.
310 * @return List<FileSystemObject> The current file list of the navigation view
312 public List<FileSystemObject> getFiles() {
313 if (this.mFiles == null) {
316 return new ArrayList<FileSystemObject>(this.mFiles);
320 * Method that returns the current file list of the navigation view.
322 * @return List<FileSystemObject> The current file list of the navigation view
324 public List<FileSystemObject> getSelectedFiles() {
325 if (this.mAdapter != null && this.mAdapter.getSelectedItems() != null) {
326 return new ArrayList<FileSystemObject>(this.mAdapter.getSelectedItems());
332 * Method that returns the custom title fragment associated with this navigation view.
334 * @return NavigationCustomTitleView The custom title view fragment
336 public NavigationCustomTitleView getCustomTitle() {
341 * Method that associates the custom title fragment with this navigation view.
343 * @param title The custom title view fragment
345 public void setCustomTitle(NavigationCustomTitleView title) {
350 * Method that returns the breadcrumb associated with this navigation view.
352 * @return Breadcrumb The breadcrumb view fragment
354 public Breadcrumb getBreadcrumb() {
355 return this.mBreadcrumb;
359 * Method that associates the breadcrumb with this navigation view.
361 * @param breadcrumb The breadcrumb view fragment
363 public void setBreadcrumb(Breadcrumb breadcrumb) {
364 this.mBreadcrumb = breadcrumb;
365 this.mBreadcrumb.addBreadcrumbListener(this);
369 * Method that sets the listener for communicate history changes.
371 * @param onHistoryListener The listener for communicate history changes
373 public void setOnHistoryListener(OnHistoryListener onHistoryListener) {
374 this.mOnHistoryListener = onHistoryListener;
378 * Method that sets the listener which communicates selection changes.
380 * @param onNavigationSelectionChangedListener The listener reference
382 public void setOnNavigationSelectionChangedListener(
383 OnNavigationSelectionChangedListener onNavigationSelectionChangedListener) {
384 this.mOnNavigationSelectionChangedListener = onNavigationSelectionChangedListener;
388 * Method that sets the listener for menu item requests.
390 * @param onNavigationRequestMenuListener The listener reference
392 public void setOnNavigationOnRequestMenuListener(
393 OnNavigationRequestMenuListener onNavigationRequestMenuListener) {
394 this.mOnNavigationRequestMenuListener = onNavigationRequestMenuListener;
398 * @return the mOnFilePickedListener
400 public OnFilePickedListener getOnFilePickedListener() {
401 return this.mOnFilePickedListener;
405 * Method that sets the listener for picked items
407 * @param onFilePickedListener The listener reference
409 public void setOnFilePickedListener(OnFilePickedListener onFilePickedListener) {
410 this.mOnFilePickedListener = onFilePickedListener;
414 * Method that forces the view to scroll to the file system object passed.
416 * @param fso The file system object
418 public void scrollTo(FileSystemObject fso) {
421 int position = this.mAdapter.getPosition(fso);
422 this.mAdapterView.setSelection(position);
423 } catch (Exception e) {
424 this.mAdapterView.setSelection(0);
430 * Method that refresh the view data.
432 public void refresh() {
433 FileSystemObject fso = null;
434 // Try to restore the previous scroll position
436 if (this.mAdapterView != null && this.mAdapter != null) {
437 int position = this.mAdapterView.getFirstVisiblePosition();
438 fso = this.mAdapter.getItem(position);
440 } catch (Throwable _throw) {/**NON BLOCK**/}
445 * Method that refresh the view data.
447 * @param scrollTo Scroll to object
449 public void refresh(FileSystemObject scrollTo) {
450 //Check that current directory was set
451 if (this.mCurrentDir == null || this.mFiles == null) {
456 changeCurrentDir(this.mCurrentDir, false, true, false, null, scrollTo);
460 * Method that change the view mode.
462 * @param newMode The new mode
464 @SuppressWarnings({ "unchecked", "null" })
465 public void changeViewMode(final NavigationLayoutMode newMode) {
466 synchronized (this.mSync) {
467 //Check that it is really necessary change the mode
468 if (this.mCurrentMode != null && this.mCurrentMode.compareTo(newMode) == 0) {
472 //Creates the new layout
473 AdapterView<ListAdapter> newView = null;
474 int itemResourceId = -1;
475 if (newMode.compareTo(NavigationLayoutMode.ICONS) == 0) {
476 newView = (AdapterView<ListAdapter>)inflate(
477 getContext(), RESOURCE_MODE_ICONS_LAYOUT, null);
478 itemResourceId = RESOURCE_MODE_ICONS_ITEM;
479 } else if (newMode.compareTo(NavigationLayoutMode.SIMPLE) == 0) {
480 newView = (AdapterView<ListAdapter>)inflate(
481 getContext(), RESOURCE_MODE_SIMPLE_LAYOUT, null);
482 itemResourceId = RESOURCE_MODE_SIMPLE_ITEM;
483 } else if (newMode.compareTo(NavigationLayoutMode.DETAILS) == 0) {
484 newView = (AdapterView<ListAdapter>)inflate(
485 getContext(), RESOURCE_MODE_DETAILS_LAYOUT, null);
486 itemResourceId = RESOURCE_MODE_DETAILS_ITEM;
489 //Get the current adapter and its adapter list
490 List<FileSystemObject> files = new ArrayList<FileSystemObject>(this.mFiles);
491 final AdapterView<ListAdapter> current =
492 (AdapterView<ListAdapter>)findViewById(RESOURCE_CURRENT_LAYOUT);
493 FileSystemObjectAdapter adapter =
494 new FileSystemObjectAdapter(
496 new ArrayList<FileSystemObject>(),
498 this.mNavigationMode.compareTo(NAVIGATION_MODE.PICKABLE) == 0);
499 adapter.setOnSelectionChangedListener(this);
501 //Remove current layout
502 if (current != null) {
503 if (current.getAdapter() != null) {
504 //Save selected items before dispose adapter
505 FileSystemObjectAdapter currentAdapter =
506 ((FileSystemObjectAdapter)current.getAdapter());
507 adapter.setSelectedItems(currentAdapter.getSelectedItems());
508 currentAdapter.dispose();
513 adapter.addAll(files);
514 adapter.notifyDataSetChanged();
517 this.mAdapter = adapter;
518 newView.setAdapter(this.mAdapter);
519 newView.setOnItemClickListener(NavigationView.this);
522 this.mAdapterView = newView;
524 this.mCurrentMode = newMode;
526 // Pick mode doesn't implements the onlongclick
527 if (this.mNavigationMode.compareTo(NAVIGATION_MODE.BROWSABLE) == 0) {
528 this.mAdapterView.setOnItemLongClickListener(this);
530 this.mAdapterView.setOnItemLongClickListener(null);
533 //Save the preference (only in navigation browse mode)
534 if (this.mNavigationMode.compareTo(NAVIGATION_MODE.BROWSABLE) == 0) {
536 Preferences.savePreference(
537 FileManagerSettings.SETTINGS_LAYOUT_MODE, newMode, true);
538 } catch (Exception ex) {
539 Log.e(TAG, "Save of view mode preference fails", ex); //$NON-NLS-1$
546 * Method that removes a {@link FileSystemObject} from the view
548 * @param fso The file system object
550 public void removeItem(FileSystemObject fso) {
551 this.mAdapter.remove(fso);
552 this.mAdapter.notifyDataSetChanged();
556 * Method that removes a file system object from his path from the view
558 * @param path The file system object path
560 public void removeItem(String path) {
561 FileSystemObject fso = this.mAdapter.getItem(path);
563 this.mAdapter.remove(fso);
564 this.mAdapter.notifyDataSetChanged();
569 * Method that returns the current directory.
571 * @return String The current directory
573 public String getCurrentDir() {
574 return this.mCurrentDir;
578 * Method that changes the current directory of the view.
580 * @param newDir The new directory location
582 public void changeCurrentDir(final String newDir) {
583 changeCurrentDir(newDir, true, false, false, null, null);
587 * Method that changes the current directory of the view.
589 * @param newDir The new directory location
590 * @param searchInfo The search information (if calling activity is {@link "SearchActivity"})
592 public void changeCurrentDir(final String newDir, SearchInfoParcelable searchInfo) {
593 changeCurrentDir(newDir, true, false, false, searchInfo, null);
597 * Method that changes the current directory of the view.
599 * @param newDir The new directory location
600 * @param addToHistory Add the directory to history
601 * @param reload Force the reload of the data
602 * @param useCurrent If this method must use the actual data (for back actions)
603 * @param searchInfo The search information (if calling activity is {@link "SearchActivity"})
604 * @param scrollTo If not null, then listview must scroll to this item
606 private void changeCurrentDir(
607 final String newDir, final boolean addToHistory,
608 final boolean reload, final boolean useCurrent,
609 final SearchInfoParcelable searchInfo, final FileSystemObject scrollTo) {
611 // Check navigation security (don't allow to go outside the ChRooted environment if one
613 final String fNewDir = checkChRootedNavigation(newDir);
615 synchronized (this.mSync) {
616 //Check that it is really necessary change the directory
617 if (!reload && this.mCurrentDir != null && this.mCurrentDir.compareTo(fNewDir) == 0) {
621 final boolean hasChanged =
622 !(this.mCurrentDir != null && this.mCurrentDir.compareTo(fNewDir) == 0);
623 final boolean isNewHistory = (this.mCurrentDir != null);
625 //Execute the listing in a background process
626 AsyncTask<String, Integer, List<FileSystemObject>> task =
627 new AsyncTask<String, Integer, List<FileSystemObject>>() {
632 protected List<FileSystemObject> doInBackground(String... params) {
634 //Reset the custom title view and returns to breadcrumb
635 if (NavigationView.this.mTitle != null) {
636 NavigationView.this.mTitle.post(new Runnable() {
640 NavigationView.this.mTitle.restoreView();
641 } catch (Exception e) {
649 //Start of loading data
650 if (NavigationView.this.mBreadcrumb != null) {
652 NavigationView.this.mBreadcrumb.startLoading();
653 } catch (Throwable ex) {
658 //Get the files, resolve links and apply configuration
659 //(sort, hidden, ...)
660 List<FileSystemObject> files = NavigationView.this.mFiles;
662 files = CommandHelper.listFiles(getContext(), fNewDir, null);
665 } catch (final ConsoleAllocException e) {
666 //Show exception and exists
667 NavigationView.this.post(new Runnable() {
670 Context ctx = getContext();
671 Log.e(TAG, ctx.getString(
672 R.string.msgs_cant_create_console), e);
673 DialogHelper.showToast(ctx,
674 R.string.msgs_cant_create_console,
676 ((Activity)ctx).finish();
681 } catch (Exception ex) {
682 //End of loading data
683 if (NavigationView.this.mBreadcrumb != null) {
685 NavigationView.this.mBreadcrumb.endLoading();
686 } catch (Throwable ex2) {
692 ExceptionUtil.attachAsyncTask(
694 new AsyncTask<Object, Integer, Boolean>() {
696 @SuppressWarnings("unchecked")
697 protected Boolean doInBackground(Object... taskParams) {
698 final List<FileSystemObject> files =
699 (List<FileSystemObject>)taskParams[0];
700 NavigationView.this.mAdapterView.post(
706 isNewHistory, hasChanged,
707 searchInfo, fNewDir, scrollTo);
714 ExceptionUtil.translateException(getContext(), ex);
723 protected void onPostExecute(List<FileSystemObject> files) {
725 files, addToHistory, isNewHistory,
726 hasChanged, searchInfo, fNewDir, scrollTo);
729 task.execute(fNewDir);
735 * Method invoked when a execution ends.
737 * @param files The files obtains from the list
738 * @param addToHistory If add path to history
739 * @param isNewHistory If is new history
740 * @param hasChanged If current directory was changed
741 * @param searchInfo The search information (if calling activity is {@link "SearchActivity"})
742 * @param newDir The new directory
743 * @param scrollTo If not null, then listview must scroll to this item
746 void onPostExecuteTask(
747 List<FileSystemObject> files, boolean addToHistory, boolean isNewHistory,
748 boolean hasChanged, SearchInfoParcelable searchInfo,
749 String newDir, final FileSystemObject scrollTo) {
751 //Check that there is not errors and have some data
756 //Apply user preferences
757 List<FileSystemObject> sortedFiles =
758 FileHelper.applyUserPreferences(files, this.mMimeType, this.mChRooted);
760 //Remove parent directory if we are in the root of a chrooted environment
761 if (this.mChRooted && StorageHelper.isStorageVolume(newDir)) {
762 if (files.size() > 0 && files.get(0) instanceof ParentDirectory) {
768 loadData(sortedFiles);
769 NavigationView.this.mFiles = sortedFiles;
770 if (searchInfo != null) {
771 searchInfo.setSuccessNavigation(true);
775 if (addToHistory && hasChanged && isNewHistory) {
776 if (NavigationView.this.mOnHistoryListener != null) {
777 //Communicate the need of a history change
778 NavigationView.this.mOnHistoryListener.onNewHistory(onSaveState());
782 //Change the breadcrumb
783 if (NavigationView.this.mBreadcrumb != null) {
784 NavigationView.this.mBreadcrumb.changeBreadcrumbPath(newDir, this.mChRooted);
788 if (scrollTo != null) {
792 //The current directory is now the "newDir"
793 NavigationView.this.mCurrentDir = newDir;
796 //If calling activity is search, then save the search history
797 if (searchInfo != null) {
798 NavigationView.this.mOnHistoryListener.onNewHistory(searchInfo);
801 //End of loading data
803 NavigationView.this.mBreadcrumb.endLoading();
804 } catch (Throwable ex) {
811 * Method that loads the files in the adapter.
813 * @param files The files to load in the adapter
816 @SuppressWarnings("unchecked")
817 private void loadData(final List<FileSystemObject> files) {
818 //Notify data to adapter view
819 final AdapterView<ListAdapter> view =
820 (AdapterView<ListAdapter>)findViewById(RESOURCE_CURRENT_LAYOUT);
821 FileSystemObjectAdapter adapter = (FileSystemObjectAdapter)view.getAdapter();
823 adapter.addAll(files);
824 adapter.notifyDataSetChanged();
825 view.setSelection(0);
832 public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
833 // Different actions depending on user preference
835 // Get the adapter and the fso
836 FileSystemObjectAdapter adapter = ((FileSystemObjectAdapter)parent.getAdapter());
837 FileSystemObject fso = adapter.getItem(position);
839 // Parent directory hasn't actions
840 if (fso instanceof ParentDirectory) {
844 // Pick mode doesn't implements the onlongclick
845 if (this.mNavigationMode.compareTo(NAVIGATION_MODE.PICKABLE) == 0) {
850 return true; //Always consume the event
854 * Method that opens or navigates to the {@link FileSystemObject}
856 * @param fso The file system object
858 public void open(FileSystemObject fso) {
863 * Method that opens or navigates to the {@link FileSystemObject}
865 * @param fso The file system object
866 * @param searchInfo The search info
868 public void open(FileSystemObject fso, SearchInfoParcelable searchInfo) {
869 // If is a folder, then navigate to
870 if (FileHelper.isDirectory(fso)) {
871 changeCurrentDir(fso.getFullPath(), searchInfo);
873 // Open the file with the preferred registered app
874 IntentsActionPolicy.openFileSystemObject(getContext(), fso, false, null, null);
882 public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
884 FileSystemObject fso = ((FileSystemObjectAdapter)parent.getAdapter()).getItem(position);
885 if (fso instanceof ParentDirectory) {
886 changeCurrentDir(fso.getParent(), true, false, false, null, null);
887 } else if (fso instanceof Directory) {
888 changeCurrentDir(fso.getFullPath(), true, false, false, null, null);
889 } else if (fso instanceof Symlink) {
890 Symlink symlink = (Symlink)fso;
891 if (symlink.getLinkRef() != null && symlink.getLinkRef() instanceof Directory) {
893 symlink.getLinkRef().getFullPath(), true, false, false, null, null);
896 if (this.mNavigationMode.compareTo(NAVIGATION_MODE.BROWSABLE) == 0) {
897 // Open the file with the preferred registered app
898 IntentsActionPolicy.openFileSystemObject(getContext(), fso, false, null, null);
900 // Request a file pick selection
901 if (this.mOnFilePickedListener != null) {
902 this.mOnFilePickedListener.onFilePicked(fso);
906 } catch (Throwable ex) {
907 ExceptionUtil.translateException(getContext(), ex);
915 public void onRequestRefresh(Object o) {
916 if (o instanceof FileSystemObject) {
917 refresh((FileSystemObject)o);
926 public void onRequestRemove(Object o) {
927 if (o instanceof FileSystemObject) {
928 removeItem((FileSystemObject)o);
937 public void onNavigateTo(Object o) {
945 public void onBreadcrumbItemClick(BreadcrumbItem item) {
946 changeCurrentDir(item.getItemPath(), true, true, false, null, null);
953 public void onSelectionChanged(final List<FileSystemObject> selectedItems) {
954 if (this.mOnNavigationSelectionChangedListener != null) {
955 this.mOnNavigationSelectionChangedListener.onSelectionChanged(this, selectedItems);
960 * Method invoked when a request to show the menu associated
961 * with an item is started.
963 * @param item The item for which the request was started
965 public void onRequestMenu(final FileSystemObject item) {
966 if (this.mOnNavigationRequestMenuListener != null) {
967 this.mOnNavigationRequestMenuListener.onRequestMenu(this, item);
975 public void onToggleSelection(FileSystemObject fso) {
976 if (this.mAdapter != null) {
977 this.mAdapter.toggleSelection(fso);
985 public void onDeselectAll() {
986 if (this.mAdapter != null) {
987 this.mAdapter.deselectedAll();
995 public void onSelectAllVisibleItems() {
996 if (this.mAdapter != null) {
997 this.mAdapter.selectedAllVisibleItems();
1005 public void onDeselectAllVisibleItems() {
1006 if (this.mAdapter != null) {
1007 this.mAdapter.deselectedAllVisibleItems();
1015 public List<FileSystemObject> onRequestSelectedFiles() {
1016 return this.getSelectedFiles();
1023 public List<FileSystemObject> onRequestCurrentItems() {
1024 return this.getFiles();
1031 public String onRequestCurrentDir() {
1032 return this.mCurrentDir;
1036 * Method that creates a ChRooted environment, protecting the user to break anything
1040 public void createChRooted() {
1041 // If we are in a ChRooted environment, then do nothing
1042 if (this.mChRooted) return;
1043 this.mChRooted = true;
1045 //Change to first storage volume
1046 StorageVolume[] volumes =
1047 StorageHelper.getStorageVolumes(getContext());
1048 if (volumes != null && volumes.length > 0) {
1049 changeCurrentDir(volumes[0].getPath(), false, true, false, null, null);
1054 * Method that exits from a ChRooted environment
1057 public void exitChRooted() {
1058 // If we aren't in a ChRooted environment, then do nothing
1059 if (!this.mChRooted) return;
1060 this.mChRooted = false;
1067 * Method that ensures that the user don't go outside the ChRooted environment
1069 * @param newDir The new directory to navigate to
1072 private String checkChRootedNavigation(String newDir) {
1073 // If we aren't in ChRooted environment, then there is nothing to check
1074 if (!this.mChRooted) return newDir;
1076 // Check if the path is owned by one of the storage volumes
1077 if (!StorageHelper.isPathInStorageVolume(newDir)) {
1078 StorageVolume[] volumes = StorageHelper.getStorageVolumes(getContext());
1079 if (volumes != null && volumes.length > 0) {
1080 return volumes[0].getPath();