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.activities;
19 import android.app.ActionBar;
20 import android.app.Activity;
21 import android.app.AlertDialog;
22 import android.app.SearchManager;
23 import android.content.BroadcastReceiver;
24 import android.content.Context;
25 import android.content.DialogInterface;
26 import android.content.Intent;
27 import android.content.IntentFilter;
28 import android.content.res.Configuration;
29 import android.net.Uri;
30 import android.nfc.NfcAdapter;
31 import android.nfc.NfcEvent;
32 import android.os.Bundle;
33 import android.os.Handler;
34 import android.os.Parcelable;
35 import android.os.storage.StorageVolume;
36 import android.util.Log;
37 import android.view.KeyEvent;
38 import android.view.Menu;
39 import android.view.MenuItem;
40 import android.view.View;
41 import android.view.ViewGroup;
42 import android.widget.AdapterView;
43 import android.widget.AdapterView.OnItemClickListener;
44 import android.widget.ImageView;
45 import android.widget.LinearLayout;
46 import android.widget.ListPopupWindow;
47 import android.widget.PopupWindow;
48 import android.widget.TextView;
49 import android.widget.Toast;
51 import com.cyanogenmod.filemanager.FileManagerApplication;
52 import com.cyanogenmod.filemanager.R;
53 import com.cyanogenmod.filemanager.activities.preferences.SettingsPreferences;
54 import com.cyanogenmod.filemanager.adapters.HighlightedSimpleMenuListAdapter;
55 import com.cyanogenmod.filemanager.adapters.MenuSettingsAdapter;
56 import com.cyanogenmod.filemanager.adapters.SimpleMenuListAdapter;
57 import com.cyanogenmod.filemanager.console.Console;
58 import com.cyanogenmod.filemanager.console.ConsoleAllocException;
59 import com.cyanogenmod.filemanager.console.ConsoleBuilder;
60 import com.cyanogenmod.filemanager.console.NoSuchFileOrDirectory;
61 import com.cyanogenmod.filemanager.listeners.OnHistoryListener;
62 import com.cyanogenmod.filemanager.listeners.OnRequestRefreshListener;
63 import com.cyanogenmod.filemanager.model.DiskUsage;
64 import com.cyanogenmod.filemanager.model.FileSystemObject;
65 import com.cyanogenmod.filemanager.model.History;
66 import com.cyanogenmod.filemanager.model.MountPoint;
67 import com.cyanogenmod.filemanager.parcelables.HistoryNavigable;
68 import com.cyanogenmod.filemanager.parcelables.NavigationViewInfoParcelable;
69 import com.cyanogenmod.filemanager.parcelables.SearchInfoParcelable;
70 import com.cyanogenmod.filemanager.preferences.AccessMode;
71 import com.cyanogenmod.filemanager.preferences.FileManagerSettings;
72 import com.cyanogenmod.filemanager.preferences.NavigationLayoutMode;
73 import com.cyanogenmod.filemanager.preferences.ObjectIdentifier;
74 import com.cyanogenmod.filemanager.preferences.Preferences;
75 import com.cyanogenmod.filemanager.ui.ThemeManager;
76 import com.cyanogenmod.filemanager.ui.ThemeManager.Theme;
77 import com.cyanogenmod.filemanager.ui.dialogs.ActionsDialog;
78 import com.cyanogenmod.filemanager.ui.dialogs.FilesystemInfoDialog;
79 import com.cyanogenmod.filemanager.ui.dialogs.FilesystemInfoDialog.OnMountListener;
80 import com.cyanogenmod.filemanager.ui.widgets.Breadcrumb;
81 import com.cyanogenmod.filemanager.ui.widgets.ButtonItem;
82 import com.cyanogenmod.filemanager.ui.widgets.NavigationCustomTitleView;
83 import com.cyanogenmod.filemanager.ui.widgets.NavigationView;
84 import com.cyanogenmod.filemanager.ui.widgets.NavigationView.OnNavigationRequestMenuListener;
85 import com.cyanogenmod.filemanager.ui.widgets.NavigationView.OnNavigationSelectionChangedListener;
86 import com.cyanogenmod.filemanager.ui.widgets.SelectionView;
87 import com.cyanogenmod.filemanager.util.AndroidHelper;
88 import com.cyanogenmod.filemanager.util.CommandHelper;
89 import com.cyanogenmod.filemanager.util.DialogHelper;
90 import com.cyanogenmod.filemanager.util.ExceptionUtil;
91 import com.cyanogenmod.filemanager.util.FileHelper;
92 import com.cyanogenmod.filemanager.util.StorageHelper;
95 import java.io.FileNotFoundException;
96 import java.io.Serializable;
97 import java.util.ArrayList;
98 import java.util.Arrays;
99 import java.util.List;
102 * The main navigation activity. This activity is the center of the application.
103 * From this the user can navigate, search, make actions.<br/>
104 * This activity is singleTop, so when it is displayed no other activities exists in
106 * This cause an issue with the saved instance of this class, because if another activity
107 * is displayed, and the process is killed, NavigationActivity is started and the saved
108 * instance gets corrupted.<br/>
109 * For this reason the methods {link {@link Activity#onSaveInstanceState(Bundle)} and
110 * {@link Activity#onRestoreInstanceState(Bundle)} are not implemented, and every time
111 * the app is killed, is restarted from his initial state.
113 public class NavigationActivity extends Activity
114 implements OnHistoryListener, OnRequestRefreshListener,
115 OnNavigationRequestMenuListener, OnNavigationSelectionChangedListener {
117 private static final String TAG = "NavigationActivity"; //$NON-NLS-1$
119 private static boolean DEBUG = false;
122 * Intent code for request a bookmark selection.
124 public static final int INTENT_REQUEST_BOOKMARK = 10001;
127 * Intent code for request a history selection.
129 public static final int INTENT_REQUEST_HISTORY = 20001;
132 * Intent code for request a search.
134 public static final int INTENT_REQUEST_SEARCH = 30001;
138 * Constant for extra information about selected bookmark.
140 public static final String EXTRA_BOOKMARK_SELECTION =
141 "extra_bookmark_selection"; //$NON-NLS-1$
144 * Constant for extra information about selected history entry.
146 public static final String EXTRA_HISTORY_ENTRY_SELECTION =
147 "extra_history_entry_selection"; //$NON-NLS-1$
150 * Constant for extra information about clear selection action.
152 public static final String EXTRA_HISTORY_CLEAR =
153 "extra_history_clear_history"; //$NON-NLS-1$
156 * Constant for extra information about selected search entry.
158 public static final String EXTRA_SEARCH_ENTRY_SELECTION =
159 "extra_search_entry_selection"; //$NON-NLS-1$
162 * Constant for extra information about last search data.
164 public static final String EXTRA_SEARCH_LAST_SEARCH_DATA =
165 "extra_search_last_search_data"; //$NON-NLS-1$
168 * Constant for extra information for request a navigation to the passed path.
170 public static final String EXTRA_NAVIGATE_TO =
171 "extra_navigate_to"; //$NON-NLS-1$
173 // The timeout needed to reset the exit status for back button
174 // After this time user need to tap 2 times the back button to
175 // exit, and the toast is shown again after the first tap.
176 private static final int RELEASE_EXIT_CHECK_TIMEOUT = 3500;
178 private final BroadcastReceiver mNotificationReceiver = new BroadcastReceiver() {
180 public void onReceive(Context context, Intent intent) {
181 if (intent != null) {
182 if (intent.getAction().compareTo(FileManagerSettings.INTENT_SETTING_CHANGED) == 0) {
183 // The settings has changed
184 String key = intent.getStringExtra(FileManagerSettings.EXTRA_SETTING_CHANGED_KEY);
186 // Disk usage warning level
187 if (key.compareTo(FileManagerSettings.
188 SETTINGS_DISK_USAGE_WARNING_LEVEL.getId()) == 0) {
190 // Set the free disk space warning level of the breadcrumb widget
191 Breadcrumb breadcrumb = getCurrentNavigationView().getBreadcrumb();
192 String fds = Preferences.getSharedPreferences().getString(
193 FileManagerSettings.SETTINGS_DISK_USAGE_WARNING_LEVEL.getId(),
194 (String)FileManagerSettings.
195 SETTINGS_DISK_USAGE_WARNING_LEVEL.getDefaultValue());
196 breadcrumb.setFreeDiskSpaceWarningLevel(Integer.parseInt(fds));
197 breadcrumb.updateMountPointInfo();
201 // Case sensitive sort
202 if (key.compareTo(FileManagerSettings.
203 SETTINGS_CASE_SENSITIVE_SORT.getId()) == 0) {
204 getCurrentNavigationView().refresh();
209 if (key.compareTo(FileManagerSettings.
210 SETTINGS_USE_FLINGER.getId()) == 0) {
212 Preferences.getSharedPreferences().getBoolean(
213 FileManagerSettings.SETTINGS_USE_FLINGER.getId(),
214 ((Boolean)FileManagerSettings.
215 SETTINGS_USE_FLINGER.
216 getDefaultValue()).booleanValue());
217 getCurrentNavigationView().setUseFlinger(useFlinger);
222 if (key.compareTo(FileManagerSettings.
223 SETTINGS_ACCESS_MODE.getId()) == 0) {
224 // Is it necessary to create or exit of the ChRooted?
226 FileManagerApplication.
227 getAccessMode().compareTo(AccessMode.SAFE) == 0;
228 if (chRooted != NavigationActivity.this.mChRooted) {
238 } else if (intent.getAction().compareTo(
239 FileManagerSettings.INTENT_FILE_CHANGED) == 0) {
240 // Retrieve the file that was changed
242 intent.getStringExtra(FileManagerSettings.EXTRA_FILE_CHANGED_KEY);
244 FileSystemObject fso = CommandHelper.getFileInfo(context, file, null);
246 getCurrentNavigationView().refresh(fso);
248 } catch (Exception e) {
249 ExceptionUtil.translateException(context, e, true, false);
251 } else if (intent.getAction().compareTo(
252 FileManagerSettings.INTENT_THEME_CHANGED) == 0) {
262 NavigationView[] mNavigationViews;
263 private List<History> mHistory;
265 private int mCurrentNavigationView;
267 private ViewGroup mActionBar;
268 private SelectionView mSelectionBar;
270 private boolean mExitFlag = false;
271 private long mExitBackTimeout = -1;
273 private View mOptionsAnchorView;
275 private int mOrientation;
291 protected void onCreate(Bundle state) {
294 Log.d(TAG, "NavigationActivity.onCreate"); //$NON-NLS-1$
297 // Register the broadcast receiver
298 IntentFilter filter = new IntentFilter();
299 filter.addAction(FileManagerSettings.INTENT_SETTING_CHANGED);
300 filter.addAction(FileManagerSettings.INTENT_FILE_CHANGED);
301 filter.addAction(FileManagerSettings.INTENT_THEME_CHANGED);
302 registerReceiver(this.mNotificationReceiver, filter);
304 //Set the main layout of the activity
305 setContentView(R.layout.navigation);
307 //Initialize nfc adapter
308 NfcAdapter mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
309 if (mNfcAdapter != null) {
310 mNfcAdapter.setBeamPushUrisCallback(new NfcAdapter.CreateBeamUrisCallback() {
312 public Uri[] createBeamUris(NfcEvent event) {
313 List<FileSystemObject> selectedFiles =
314 getCurrentNavigationView().getSelectedFiles();
315 if (selectedFiles.size() > 0) {
316 List<Uri> fileUri = new ArrayList<Uri>();
317 for (FileSystemObject f : selectedFiles) {
318 //Beam ignores folders and system files
319 if (!FileHelper.isDirectory(f) && !FileHelper.isSystemFile(f)) {
320 fileUri.add(Uri.fromFile(new File(f.getFullPath())));
323 if (fileUri.size() > 0) {
324 return fileUri.toArray(new Uri[fileUri.size()]);
332 //Initialize activity
336 initNavigationViews();
338 //Initialize action bars
339 initTitleActionBar();
340 initStatusActionBar();
343 // Adjust layout (only when start on landscape mode)
344 int orientation = getResources().getConfiguration().orientation;
345 if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
348 this.mOrientation = orientation;
353 // Show welcome message
356 this.mHandler = new Handler();
357 this.mHandler.post(new Runnable() {
360 //Initialize navigation
361 int cc = NavigationActivity.this.mNavigationViews.length;
362 for (int i = 0; i < cc; i++) {
363 initNavigation(i, false);
366 //Check the intent action
367 checkIntent(getIntent());
372 super.onCreate(state);
379 protected void onNewIntent(Intent intent) {
380 //Initialize navigation
381 initNavigation(this.mCurrentNavigationView, true);
383 //Check the intent action
391 public void onConfigurationChanged(Configuration newConfig) {
392 super.onConfigurationChanged(newConfig);
400 protected void onDestroy() {
402 Log.d(TAG, "NavigationActivity.onDestroy"); //$NON-NLS-1$
405 // Unregister the receiver
407 unregisterReceiver(this.mNotificationReceiver);
408 } catch (Throwable ex) {
412 //All destroy. Continue
417 * Method that returns the current navigation view.
419 * @return NavigationView The current navigation view
421 public NavigationView getCurrentNavigationView() {
422 return getNavigationView(this.mCurrentNavigationView);
426 * Method that returns the current navigation view.
428 * @param viewId The view to return
429 * @return NavigationView The current navigation view
431 public NavigationView getNavigationView(int viewId) {
432 if (this.mNavigationViews == null) return null;
433 return this.mNavigationViews[viewId];
437 * Method that initializes the activity.
439 private void init() {
440 this.mHistory = new ArrayList<History>();
441 this.mChRooted = FileManagerApplication.getAccessMode().compareTo(AccessMode.SAFE) == 0;
445 * Method that displays a welcome message the first time the user
446 * access the application
448 private void showWelcomeMsg() {
449 boolean firstUse = Preferences.getSharedPreferences().getBoolean(
450 FileManagerSettings.SETTINGS_FIRST_USE.getId(),
451 ((Boolean)FileManagerSettings.SETTINGS_FIRST_USE.getDefaultValue()).booleanValue());
453 //Display the welcome message?
455 AlertDialog dialog = DialogHelper.createAlertDialog(
456 this, R.drawable.ic_launcher,
457 R.string.welcome_title, getString(R.string.welcome_msg), false);
458 DialogHelper.delegateDialogShow(this, dialog);
460 // Don't display again this dialog
462 Preferences.savePreference(
463 FileManagerSettings.SETTINGS_FIRST_USE, Boolean.FALSE, true);
464 } catch (Exception e) {/**NON BLOCK**/}
469 * Method that initializes the titlebar of the activity.
471 private void initTitleActionBar() {
472 //Inflate the view and associate breadcrumb
473 View titleLayout = getLayoutInflater().inflate(
474 R.layout.navigation_view_customtitle, null, false);
475 NavigationCustomTitleView title =
476 (NavigationCustomTitleView)titleLayout.findViewById(R.id.navigation_title_flipper);
477 title.setOnHistoryListener(this);
478 Breadcrumb breadcrumb = (Breadcrumb)title.findViewById(R.id.breadcrumb_view);
479 int cc = this.mNavigationViews.length;
480 for (int i = 0; i < cc; i++) {
481 this.mNavigationViews[i].setBreadcrumb(breadcrumb);
482 this.mNavigationViews[i].setOnHistoryListener(this);
483 this.mNavigationViews[i].setOnNavigationSelectionChangedListener(this);
484 this.mNavigationViews[i].setOnNavigationOnRequestMenuListener(this);
485 this.mNavigationViews[i].setCustomTitle(title);
488 // Set the free disk space warning level of the breadcrumb widget
489 String fds = Preferences.getSharedPreferences().getString(
490 FileManagerSettings.SETTINGS_DISK_USAGE_WARNING_LEVEL.getId(),
491 (String)FileManagerSettings.SETTINGS_DISK_USAGE_WARNING_LEVEL.getDefaultValue());
492 breadcrumb.setFreeDiskSpaceWarningLevel(Integer.parseInt(fds));
494 //Configure the action bar options
495 getActionBar().setBackgroundDrawable(
496 getResources().getDrawable(R.drawable.bg_holo_titlebar));
497 getActionBar().setDisplayOptions(
498 ActionBar.DISPLAY_SHOW_CUSTOM | ActionBar.DISPLAY_SHOW_HOME);
499 getActionBar().setCustomView(titleLayout);
503 * Method that initializes the statusbar of the activity.
505 private void initStatusActionBar() {
506 //Performs a width calculation of buttons. Buttons exceeds the width
507 //of the action bar should be hidden
508 //This application not use android ActionBar because the application
509 //make uses of the title and bottom areas, and wants to force to show
510 //the overflow button (without care of physical buttons)
511 this.mActionBar = (ViewGroup)findViewById(R.id.navigation_actionbar);
512 this.mActionBar.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
514 public void onLayoutChange(
515 View v, int left, int top, int right, int bottom, int oldLeft,
516 int oldTop, int oldRight, int oldBottom) {
517 //Get the width of the action bar
518 int w = v.getMeasuredWidth();
520 //Wake through children calculation his dimensions
521 int bw = (int)getResources().getDimension(R.dimen.default_buttom_width);
523 final ViewGroup abView = ((ViewGroup)v);
524 int cc = abView.getChildCount();
525 for (int i = 0; i < cc; i++) {
526 View child = abView.getChildAt(i);
527 child.setVisibility(cw + bw > w ? View.INVISIBLE : View.VISIBLE);
533 // Have overflow menu?
534 View overflow = findViewById(R.id.ab_overflow);
535 boolean showOptionsMenu = AndroidHelper.showOptionsMenu(getApplicationContext());
536 overflow.setVisibility(showOptionsMenu ? View.VISIBLE : View.GONE);
537 this.mOptionsAnchorView = showOptionsMenu ? overflow : this.mActionBar;
539 // Show the status bar
540 View statusBar = findViewById(R.id.navigation_statusbar_portrait_holder);
541 statusBar.setVisibility(View.VISIBLE);
545 * Method that initializes the selectionbar of the activity.
547 private void initSelectionBar() {
548 this.mSelectionBar = (SelectionView)findViewById(R.id.navigation_selectionbar);
552 * Method that initializes the navigation views of the activity
554 private void initNavigationViews() {
555 //Get the navigation views (wishlist: multiple view; for now only one view)
556 this.mNavigationViews = new NavigationView[1];
557 this.mCurrentNavigationView = 0;
559 this.mNavigationViews[0] = (NavigationView)findViewById(R.id.navigation_view);
560 this.mNavigationViews[0].setId(0);
564 * Method that initializes the navigation.
566 * @param viewId The navigation view identifier where apply the navigation
567 * @param restore Initialize from a restore info
570 void initNavigation(final int viewId, final boolean restore) {
571 final NavigationView navigationView = getNavigationView(viewId);
572 this.mHandler.post(new Runnable() {
575 //Create the default console (from the preferences)
577 Console console = ConsoleBuilder.getConsole(NavigationActivity.this);
578 if (console == null) {
579 throw new ConsoleAllocException("console == null"); //$NON-NLS-1$
581 } catch (Throwable ex) {
582 if (!NavigationActivity.this.mChRooted) {
583 //Show exception and exists
584 Log.e(TAG, getString(R.string.msgs_cant_create_console), ex);
585 // We don't have any console
586 // Show exception and exists
587 DialogHelper.showToast(
588 NavigationActivity.this,
589 R.string.msgs_cant_create_console, Toast.LENGTH_LONG);
594 // We are in a trouble (something is not allowing creating the console)
595 // Ask the user to return to prompt or root access mode mode with a
596 // non-privileged console, prior to make crash the application
601 //Is necessary navigate?
603 //Load the preference initial directory
605 Preferences.getSharedPreferences().getString(
606 FileManagerSettings.SETTINGS_INITIAL_DIR.getId(),
607 (String)FileManagerSettings.
608 SETTINGS_INITIAL_DIR.getDefaultValue());
609 if (NavigationActivity.this.mChRooted) {
610 // Initial directory is the first external sdcard (sdcard, emmc, usb, ...)
611 StorageVolume[] volumes =
612 StorageHelper.getStorageVolumes(NavigationActivity.this);
613 if (volumes != null && volumes.length > 0) {
614 initialDir = volumes[0].getPath();
618 //Ensure initial is an absolute directory
620 initialDir = new File(initialDir).getAbsolutePath();
621 } catch (Throwable e) {
622 Log.e(TAG, "Resolve of initital directory fails", e); //$NON-NLS-1$
625 R.string.msgs_settings_invalid_initial_directory,
627 DialogHelper.showToast(NavigationActivity.this, msg, Toast.LENGTH_SHORT);
628 initialDir = FileHelper.ROOT_DIRECTORY;
631 // Change the current directory to the preference initial directory or the
633 String navigateTo = getIntent().getStringExtra(EXTRA_NAVIGATE_TO);
634 if (navigateTo != null && navigateTo.length() > 0) {
635 navigationView.changeCurrentDir(navigateTo);
637 navigationView.changeCurrentDir(initialDir);
645 * Method that verifies the intent passed to the activity, and checks
646 * if a request is made like Search.
648 * @param intent The intent to check
651 void checkIntent(Intent intent) {
653 if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
654 Intent searchIntent = new Intent(this, SearchActivity.class);
655 searchIntent.setAction(Intent.ACTION_SEARCH);
656 //- SearchActivity.EXTRA_SEARCH_DIRECTORY
657 searchIntent.putExtra(
658 SearchActivity.EXTRA_SEARCH_DIRECTORY,
659 getCurrentNavigationView().getCurrentDir());
660 //- SearchManager.APP_DATA
661 if (intent.getBundleExtra(SearchManager.APP_DATA) != null) {
662 Bundle bundle = new Bundle();
663 bundle.putAll(intent.getBundleExtra(SearchManager.APP_DATA));
664 searchIntent.putExtra(SearchManager.APP_DATA, bundle);
666 //-- SearchManager.QUERY
667 String query = intent.getStringExtra(SearchManager.QUERY);
669 searchIntent.putExtra(SearchManager.QUERY, query);
671 //- android.speech.RecognizerIntent.EXTRA_RESULTS
672 ArrayList<String> extraResults =
673 intent.getStringArrayListExtra(android.speech.RecognizerIntent.EXTRA_RESULTS);
674 if (extraResults != null) {
675 searchIntent.putStringArrayListExtra(
676 android.speech.RecognizerIntent.EXTRA_RESULTS, extraResults);
678 startActivityForResult(searchIntent, INTENT_REQUEST_SEARCH);
682 // Navigate to the requested path
683 String navigateTo = intent.getStringExtra(EXTRA_NAVIGATE_TO);
684 if (navigateTo != null && navigateTo.length() >= 0) {
685 getCurrentNavigationView().changeCurrentDir(navigateTo);
693 public boolean onKeyUp(int keyCode, KeyEvent event) {
694 if (keyCode == KeyEvent.KEYCODE_MENU) {
695 showOverflowPopUp(this.mOptionsAnchorView);
698 if (keyCode == KeyEvent.KEYCODE_BACK) {
699 if (checkBackAction()) {
703 // An exit event has occurred, force the destroy the consoles
706 return super.onKeyUp(keyCode, event);
713 public boolean onOptionsItemSelected(MenuItem item) {
714 switch (item.getItemId()) {
715 case android.R.id.home:
716 if ((getActionBar().getDisplayOptions() & ActionBar.DISPLAY_HOME_AS_UP)
717 == ActionBar.DISPLAY_HOME_AS_UP) {
722 return super.onOptionsItemSelected(item);
727 * Method invoked when an action item is clicked.
729 * @param view The button pushed
731 public void onActionBarItemClick(View view) {
732 switch (view.getId()) {
733 //######################
734 //Navigation Custom Title
735 //######################
736 case R.id.ab_configuration:
737 //Show navigation view configuration toolbar
738 getCurrentNavigationView().getCustomTitle().showConfigurationView();
739 getActionBar().setDisplayHomeAsUpEnabled(true);
740 getActionBar().setHomeButtonEnabled(true);
743 //Hide navigation view configuration toolbar
744 getCurrentNavigationView().getCustomTitle().hideConfigurationView();
747 //######################
749 //######################
750 case R.id.ab_filesystem_info:
751 //Show information of the filesystem
752 MountPoint mp = getCurrentNavigationView().getBreadcrumb().getMountPointInfo();
753 DiskUsage du = getCurrentNavigationView().getBreadcrumb().getDiskUsageInfo();
754 showMountPointInfo(mp, du);
757 //######################
758 //Navigation view options
759 //######################
760 case R.id.ab_sort_mode:
761 showSettingsPopUp(view,
763 new FileManagerSettings[]{
764 FileManagerSettings.SETTINGS_SORT_MODE}));
766 case R.id.ab_layout_mode:
767 showSettingsPopUp(view,
769 new FileManagerSettings[]{
770 FileManagerSettings.SETTINGS_LAYOUT_MODE}));
772 case R.id.ab_view_options:
773 // If we are in ChRooted mode, then don't show non-secure items
774 if (this.mChRooted) {
775 showSettingsPopUp(view,
776 Arrays.asList(new FileManagerSettings[]{
777 FileManagerSettings.SETTINGS_SHOW_DIRS_FIRST}));
779 showSettingsPopUp(view,
780 Arrays.asList(new FileManagerSettings[]{
781 FileManagerSettings.SETTINGS_SHOW_DIRS_FIRST,
782 FileManagerSettings.SETTINGS_SHOW_HIDDEN,
783 FileManagerSettings.SETTINGS_SHOW_SYSTEM,
784 FileManagerSettings.SETTINGS_SHOW_SYMLINKS}));
789 //######################
791 //######################
792 case R.id.ab_selection_done:
793 //Show information of the filesystem
794 getCurrentNavigationView().onDeselectAll();
797 //######################
799 //######################
800 case R.id.ab_actions:
801 openActionsDialog(getCurrentNavigationView().getCurrentDir(), true);
804 case R.id.ab_bookmarks:
808 case R.id.ab_history:
816 case R.id.ab_overflow:
817 showOverflowPopUp(view);
829 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
831 switch (requestCode) {
832 case INTENT_REQUEST_BOOKMARK:
833 if (resultCode == RESULT_OK) {
834 FileSystemObject fso =
835 (FileSystemObject)data.
836 getSerializableExtra(EXTRA_BOOKMARK_SELECTION);
839 getCurrentNavigationView().open(fso);
844 case INTENT_REQUEST_HISTORY:
845 if (resultCode == RESULT_OK) {
846 //Change current directory
848 (History)data.getSerializableExtra(EXTRA_HISTORY_ENTRY_SELECTION);
849 navigateToHistory(history);
850 } else if (resultCode == RESULT_CANCELED) {
851 boolean clear = data.getBooleanExtra(EXTRA_HISTORY_CLEAR, false);
858 case INTENT_REQUEST_SEARCH:
859 if (resultCode == RESULT_OK) {
861 FileSystemObject fso =
862 (FileSystemObject)data.
863 getSerializableExtra(EXTRA_SEARCH_ENTRY_SELECTION);
864 SearchInfoParcelable searchInfo =
865 data.getParcelableExtra(EXTRA_SEARCH_LAST_SEARCH_DATA);
867 //Goto to new directory
868 getCurrentNavigationView().open(fso, searchInfo);
870 } else if (resultCode == RESULT_CANCELED) {
871 SearchInfoParcelable searchInfo =
872 data.getParcelableExtra(EXTRA_SEARCH_LAST_SEARCH_DATA);
873 if (searchInfo != null && searchInfo.isSuccessNavigation()) {
874 //Navigate to previous history
877 // I don't know is the search view was changed, so try to do a refresh
878 // of the navigation view
879 getCurrentNavigationView().refresh(true);
894 public void onNewHistory(HistoryNavigable navigable) {
895 //Recollect information about current status
896 History history = new History(this.mHistory.size(), navigable);
897 this.mHistory.add(history);
898 getActionBar().setDisplayHomeAsUpEnabled(true);
899 getActionBar().setHomeButtonEnabled(true);
906 public void onCheckHistory() {
907 //Need to show HomeUp Button
908 boolean enabled = this.mHistory != null && this.mHistory.size() > 0;
909 getActionBar().setDisplayHomeAsUpEnabled(enabled);
910 getActionBar().setHomeButtonEnabled(enabled);
917 public void onRequestRefresh(Object o, boolean clearSelection) {
918 if (o instanceof FileSystemObject) {
919 // Refresh only the item
920 this.getCurrentNavigationView().refresh((FileSystemObject)o);
921 } else if (o == null) {
923 getCurrentNavigationView().refresh();
925 if (clearSelection) {
926 this.getCurrentNavigationView().onDeselectAll();
934 public void onRequestRemove(Object o, boolean clearSelection) {
935 if (o instanceof FileSystemObject) {
937 this.getCurrentNavigationView().removeItem((FileSystemObject)o);
939 //Remove from history
940 removeFromHistory((FileSystemObject)o);
942 onRequestRefresh(null, clearSelection);
944 if (clearSelection) {
945 this.getCurrentNavigationView().onDeselectAll();
953 public void onNavigateTo(Object o) {
961 public void onSelectionChanged(NavigationView navView, List<FileSystemObject> selectedItems) {
962 this.mSelectionBar.setSelection(selectedItems);
969 public void onRequestMenu(NavigationView navView, FileSystemObject item) {
970 // Show the actions dialog
971 openActionsDialog(item, false);
975 * Method that shows a popup with a menu associated a {@link FileManagerSettings}.
977 * @param anchor The action button that was pressed
978 * @param settings The array of settings associated with the action button
980 private void showSettingsPopUp(View anchor, List<FileManagerSettings> settings) {
982 final MenuSettingsAdapter adapter = new MenuSettingsAdapter(this, settings);
984 //Create a show the popup menu
985 final ListPopupWindow popup = DialogHelper.createListPopupWindow(this, adapter, anchor);
986 popup.setOnItemClickListener(new OnItemClickListener() {
988 public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
989 FileManagerSettings setting =
990 ((MenuSettingsAdapter)parent.getAdapter()).getSetting(position);
991 final int value = ((MenuSettingsAdapter)parent.getAdapter()).getId(position);
994 if (setting.compareTo(FileManagerSettings.SETTINGS_LAYOUT_MODE) == 0) {
995 //Need to change the layout
996 getCurrentNavigationView().changeViewMode(
997 NavigationLayoutMode.fromId(value));
1000 if (setting.getDefaultValue() instanceof Enum<?>) {
1002 Preferences.savePreference(setting, new ObjectIdentifier() {
1004 public int getId() {
1011 Preferences.getSharedPreferences().
1014 ((Boolean)setting.getDefaultValue()).booleanValue());
1015 Preferences.savePreference(setting, Boolean.valueOf(!newval), false);
1017 getCurrentNavigationView().refresh();
1019 } catch (Exception e) {
1020 Log.e(TAG, "Error applying navigation option", e); //$NON-NLS-1$
1021 NavigationActivity.this.mHandler.post(new Runnable() {
1024 DialogHelper.showToast(
1025 NavigationActivity.this,
1026 R.string.msgs_settings_save_failure, Toast.LENGTH_SHORT);
1032 getCurrentNavigationView().getCustomTitle().restoreView();
1037 popup.setOnDismissListener(new PopupWindow.OnDismissListener() {
1039 public void onDismiss() {
1047 * Method that shows a popup with the activity main menu.
1049 * @param anchor The action button that was pressed
1051 private void showOverflowPopUp(View anchor) {
1052 SimpleMenuListAdapter adapter =
1053 new HighlightedSimpleMenuListAdapter(this, R.menu.navigation);
1054 Menu menu = adapter.getMenu();
1055 int cc = this.mActionBar.getChildCount();
1056 for (int i = 0, j = this.mActionBar.getChildCount() - 1; i < cc; i++, j--) {
1057 View child = this.mActionBar.getChildAt(i);
1058 boolean visible = child.getVisibility() == View.VISIBLE;
1060 menu.removeItem(menu.getItem(j).getItemId());
1064 final ListPopupWindow popup = DialogHelper.createListPopupWindow(this, adapter, anchor);
1065 popup.setOnItemClickListener(new OnItemClickListener() {
1067 public void onItemClick(
1068 final AdapterView<?> parent, final View v, final int position, final long id) {
1070 final int itemId = (int)id;
1071 NavigationActivity.this.mHandler.post(new Runnable() {
1076 case R.id.mnu_settings:
1078 Intent settings = new Intent(
1079 NavigationActivity.this, SettingsPreferences.class);
1080 startActivity(settings);
1083 case R.id.mnu_history:
1089 case R.id.mnu_bookmarks:
1095 case R.id.mnu_search:
1111 * Method that show the information of a filesystem mount point.
1113 * @param mp The mount point info
1114 * @param du The disk usage of the mount point
1116 private void showMountPointInfo(MountPoint mp, DiskUsage du) {
1117 //Has mount point info?
1119 //There is no information
1121 DialogHelper.createWarningDialog(
1123 R.string.filesystem_info_warning_title,
1124 R.string.filesystem_info_warning_msg);
1125 DialogHelper.delegateDialogShow(this, alert);
1129 //Show a the filesystem info dialog
1130 FilesystemInfoDialog dialog = new FilesystemInfoDialog(this, mp, du);
1131 dialog.setOnMountListener(new OnMountListener() {
1133 public void onRemount(MountPoint mountPoint) {
1134 //Update the statistics of breadcrumb, only if mount point is the same
1135 Breadcrumb breadcrumb = getCurrentNavigationView().getBreadcrumb();
1136 if (breadcrumb.getMountPointInfo().compareTo(mountPoint) == 0) {
1137 breadcrumb.updateMountPointInfo();
1145 * Method that checks the action that must be realized when the
1146 * back button is pushed.
1148 * @return boolean Indicates if the action must be intercepted
1150 private boolean checkBackAction() {
1151 // We need a basic structure to check this
1152 if (getCurrentNavigationView() == null) return false;
1154 //Check if the configuration view is showing. In this case back
1155 //action must be "close configuration"
1156 if (getCurrentNavigationView().getCustomTitle().isConfigurationViewShowing()) {
1157 getCurrentNavigationView().getCustomTitle().restoreView();
1161 //Do back operation over the navigation history
1162 boolean flag = this.mExitFlag;
1164 this.mExitFlag = !back();
1166 // Retrieve if the exit status timeout has expired
1167 long now = System.currentTimeMillis();
1168 boolean timeout = (this.mExitBackTimeout == -1 ||
1169 (now - this.mExitBackTimeout) > RELEASE_EXIT_CHECK_TIMEOUT);
1171 //Check if there no history and if the user was advised in the last back action
1172 if (this.mExitFlag && (this.mExitFlag != flag || timeout)) {
1173 //Communicate the user that the next time the application will be closed
1174 this.mExitBackTimeout = System.currentTimeMillis();
1175 DialogHelper.showToast(this, R.string.msgs_push_again_to_exit, Toast.LENGTH_SHORT);
1179 //Back action not applied
1180 return !this.mExitFlag;
1187 public boolean onSearchRequested() {
1188 Bundle bundle = new Bundle();
1190 SearchActivity.EXTRA_SEARCH_DIRECTORY,
1191 getCurrentNavigationView().getCurrentDir());
1192 startSearch(Preferences.getLastSearch(), true, bundle, false);
1197 * Method that returns the history size.
1199 private void clearHistory() {
1200 this.mHistory.clear();
1205 * Method that navigates to the passed history reference.
1207 * @param history The history reference
1208 * @return boolean A problem occurs while navigate
1210 public boolean navigateToHistory(History history) {
1213 History realHistory = this.mHistory.get(history.getPosition());
1215 //Navigate to item. Check what kind of history is
1216 if (realHistory.getItem() instanceof NavigationViewInfoParcelable) {
1218 NavigationViewInfoParcelable info =
1219 (NavigationViewInfoParcelable)realHistory.getItem();
1220 int viewId = info.getId();
1221 NavigationView view = getNavigationView(viewId);
1222 // Selected items must not be restored from on history navigation
1223 info.setSelectedFiles(view.getSelectedFiles());
1224 view.onRestoreState(info);
1226 } else if (realHistory.getItem() instanceof SearchInfoParcelable) {
1227 //Search (open search with the search results)
1228 SearchInfoParcelable info = (SearchInfoParcelable)realHistory.getItem();
1229 Intent searchIntent = new Intent(this, SearchActivity.class);
1230 searchIntent.setAction(SearchActivity.ACTION_RESTORE);
1231 searchIntent.putExtra(SearchActivity.EXTRA_SEARCH_RESTORE, (Parcelable)info);
1232 startActivityForResult(searchIntent, INTENT_REQUEST_SEARCH);
1234 //The type is unknown
1235 throw new IllegalArgumentException("Unknown history type"); //$NON-NLS-1$
1238 //Remove the old history
1239 int cc = realHistory.getPosition();
1240 for (int i = this.mHistory.size() - 1; i >= cc; i--) {
1241 this.mHistory.remove(i);
1243 if (this.mHistory.size() == 0) {
1244 getActionBar().setDisplayHomeAsUpEnabled(false);
1245 getActionBar().setHomeButtonEnabled(false);
1251 } catch (Throwable ex) {
1252 if (history != null) {
1254 String.format("Failed to navigate to history %d: %s", //$NON-NLS-1$
1255 Integer.valueOf(history.getPosition()),
1256 history.getItem().getTitle()), ex);
1259 String.format("Failed to navigate to history: null", ex)); //$NON-NLS-1$
1261 this.mHandler.post(new Runnable() {
1264 DialogHelper.showToast(
1265 NavigationActivity.this,
1266 R.string.msgs_history_unknown, Toast.LENGTH_LONG);
1270 //Not change directory
1276 * Method that request a back action over the navigation history.
1278 * @return boolean If a back action was applied
1280 public boolean back() {
1281 // Check that has valid history
1282 while (this.mHistory.size() > 0) {
1283 History h = this.mHistory.get(this.mHistory.size() - 1);
1284 if (h.getItem() instanceof NavigationViewInfoParcelable) {
1285 // Verify that the path exists
1286 String path = ((NavigationViewInfoParcelable)h.getItem()).getCurrentDir();
1289 FileSystemObject info = CommandHelper.getFileInfo(this, path, null);
1293 this.mHistory.remove(this.mHistory.size() - 1);
1294 } catch (Exception e) {
1295 ExceptionUtil.translateException(this, e, true, false);
1296 this.mHistory.remove(this.mHistory.size() - 1);
1303 //Extract a history from the
1304 if (this.mHistory.size() > 0) {
1305 //Navigate to history
1306 return navigateToHistory(this.mHistory.get(this.mHistory.size() - 1));
1314 * Method that opens the actions dialog
1316 * @param item The path or the {@link FileSystemObject}
1317 * @param global If the menu to display is the one with global actions
1319 private void openActionsDialog(Object item, boolean global) {
1320 // Resolve the full path
1321 String path = String.valueOf(item);
1322 if (item instanceof FileSystemObject) {
1323 path = ((FileSystemObject)item).getFullPath();
1326 // Prior to show the dialog, refresh the item reference
1327 FileSystemObject fso = null;
1329 fso = CommandHelper.getFileInfo(this, path, false, null);
1331 throw new NoSuchFileOrDirectory(path);
1334 } catch (Exception e) {
1336 ExceptionUtil.translateException(this, e);
1338 // Remove the object
1339 if (e instanceof FileNotFoundException || e instanceof NoSuchFileOrDirectory) {
1340 // If have a FileSystemObject reference then there is no need to search
1341 // the path (less resources used)
1342 if (item instanceof FileSystemObject) {
1343 getCurrentNavigationView().removeItem((FileSystemObject)item);
1345 getCurrentNavigationView().removeItem((String)item);
1352 ActionsDialog dialog = new ActionsDialog(this, fso, global, false);
1353 dialog.setOnRequestRefreshListener(this);
1354 dialog.setOnSelectionListener(getCurrentNavigationView());
1359 * Method that opens the bookmarks activity.
1362 void openBookmarks() {
1363 Intent bookmarksIntent = new Intent(this, BookmarksActivity.class);
1364 bookmarksIntent.addFlags(Intent.FLAG_ACTIVITY_TASK_ON_HOME);
1365 startActivityForResult(bookmarksIntent, INTENT_REQUEST_BOOKMARK);
1369 * Method that opens the history activity.
1372 void openHistory() {
1373 Intent historyIntent = new Intent(this, HistoryActivity.class);
1374 historyIntent.putExtra(HistoryActivity.EXTRA_HISTORY_LIST, (Serializable)this.mHistory);
1375 historyIntent.addFlags(Intent.FLAG_ACTIVITY_TASK_ON_HOME);
1376 startActivityForResult(historyIntent, INTENT_REQUEST_HISTORY);
1380 * Method that opens the search activity.
1384 onSearchRequested();
1388 * Method that remove the {@link FileSystemObject} from the history
1390 private void removeFromHistory(FileSystemObject fso) {
1391 if (this.mHistory != null) {
1392 int cc = this.mHistory.size();
1393 for (int i = cc-1; i >= 0 ; i--) {
1394 History history = this.mHistory.get(i);
1395 if (history.getItem() instanceof NavigationViewInfoParcelable) {
1396 String p0 = fso.getFullPath();
1398 ((NavigationViewInfoParcelable)history.getItem()).getCurrentDir();
1399 if (p0.compareTo(p1) == 0) {
1400 this.mHistory.remove(i);
1408 * Method that ask the user to change the access mode prior to crash.
1412 //Show a dialog asking the user
1413 AlertDialog dialog =
1414 DialogHelper.createYesNoDialog(
1416 R.string.msgs_change_to_prompt_access_mode_title,
1417 R.string.msgs_change_to_prompt_access_mode_msg,
1418 new DialogInterface.OnClickListener() {
1420 public void onClick(DialogInterface alertDialog, int which) {
1421 if (which == DialogInterface.BUTTON_NEGATIVE) {
1422 // We don't have any console
1423 // Show exception and exists
1424 DialogHelper.showToast(
1425 NavigationActivity.this,
1426 R.string.msgs_cant_create_console, Toast.LENGTH_LONG);
1431 // Ok. Now try to change to prompt mode. Any crash
1432 // here is a fatal error. We won't have any console to operate.
1435 ConsoleBuilder.changeToNonPrivilegedConsole(NavigationActivity.this);
1438 Preferences.savePreference(
1439 FileManagerSettings.SETTINGS_ACCESS_MODE,
1440 AccessMode.PROMPT, true);
1442 } catch (Exception e) {
1443 // Displays an exception and exit
1444 Log.e(TAG, getString(R.string.msgs_cant_create_console), e);
1445 DialogHelper.showToast(
1446 NavigationActivity.this,
1447 R.string.msgs_cant_create_console, Toast.LENGTH_LONG);
1452 DialogHelper.delegateDialogShow(this, dialog);
1456 * Method that creates a ChRooted environment, protecting the user to break anything in
1460 void createChRooted() {
1461 // If we are in a ChRooted mode, then do nothing
1462 if (this.mChRooted) return;
1463 this.mChRooted = true;
1465 int cc = this.mNavigationViews.length;
1466 for (int i = 0; i < cc; i++) {
1467 this.mNavigationViews[i].createChRooted();
1470 // Remove the selection
1471 cc = this.mNavigationViews.length;
1472 for (int i = 0; i < cc; i++) {
1473 getCurrentNavigationView().onDeselectAll();
1476 // Remove the history (don't allow to access to previous data)
1481 * Method that exits from a ChRooted
1484 void exitChRooted() {
1485 // If we aren't in a ChRooted mode, then do nothing
1486 if (!this.mChRooted) return;
1487 this.mChRooted = false;
1489 int cc = this.mNavigationViews.length;
1490 for (int i = 0; i < cc; i++) {
1491 this.mNavigationViews[i].exitChRooted();
1496 * Method called when a controlled exit is required
1501 FileManagerApplication.destroyBackgroundConsole();
1502 } catch (Throwable ex) {
1506 ConsoleBuilder.destroyConsole();
1507 } catch (Throwable ex) {
1514 * Method that reconfigures the layout for better fit in portrait and landscape modes
1516 private void onLayoutChanged() {
1517 Theme theme = ThemeManager.getCurrentTheme(this);
1519 // Apply only when the orientation was changed
1520 int orientation = getResources().getConfiguration().orientation;
1521 if (this.mOrientation == orientation) return;
1522 this.mOrientation = orientation;
1524 if (this.mOrientation == Configuration.ORIENTATION_LANDSCAPE) {
1526 ViewGroup statusBar = (ViewGroup)findViewById(R.id.navigation_statusbar);
1527 if (statusBar.getParent() != null) {
1528 ViewGroup parent = (ViewGroup) statusBar.getParent();
1529 parent.removeView(statusBar);
1532 // Calculate the action button size (all the buttons must fit in the title bar)
1533 int bw = (int)getResources().getDimension(R.dimen.default_buttom_width);
1534 int abw = this.mActionBar.getChildCount() * bw;
1536 int cc = statusBar.getChildCount();
1537 for (int i = 0; i < cc; i++) {
1538 View child = statusBar.getChildAt(i);
1539 if (child instanceof ButtonItem) {
1544 boolean showOptionsMenu = AndroidHelper.showOptionsMenu(getApplicationContext());
1545 if (!showOptionsMenu) {
1549 // Add to the new location
1550 ViewGroup newParent = (ViewGroup)findViewById(R.id.navigation_title_landscape_holder);
1551 LinearLayout.LayoutParams params =
1552 new LinearLayout.LayoutParams(
1554 ViewGroup.LayoutParams.MATCH_PARENT);
1555 statusBar.setLayoutParams(params);
1556 newParent.addView(statusBar);
1559 theme.setBackgroundDrawable(this, statusBar, "titlebar_drawable"); //$NON-NLS-1$
1562 View holder = findViewById(R.id.navigation_statusbar_portrait_holder);
1563 holder.setVisibility(View.GONE);
1567 ViewGroup statusBar = (ViewGroup)findViewById(R.id.navigation_statusbar);
1568 if (statusBar.getParent() != null) {
1569 ViewGroup parent = (ViewGroup) statusBar.getParent();
1570 parent.removeView(statusBar);
1573 // Add to the new location
1574 ViewGroup newParent = (ViewGroup)findViewById(
1575 R.id.navigation_statusbar_portrait_holder);
1576 LinearLayout.LayoutParams params =
1577 new LinearLayout.LayoutParams(
1578 ViewGroup.LayoutParams.MATCH_PARENT,
1579 ViewGroup.LayoutParams.MATCH_PARENT);
1580 statusBar.setLayoutParams(params);
1581 newParent.addView(statusBar);
1584 theme.setBackgroundDrawable(this, statusBar, "statusbar_drawable"); //$NON-NLS-1$
1587 newParent.setVisibility(View.VISIBLE);
1592 * Method that applies the current theme to the activity
1596 int orientation = getResources().getConfiguration().orientation;
1597 Theme theme = ThemeManager.getCurrentTheme(this);
1598 theme.setBaseTheme(this, false);
1601 View v = findViewById(R.id.navigation_layout);
1602 theme.setBackgroundDrawable(this, v, "background_drawable"); //$NON-NLS-1$
1604 theme.setTitlebarDrawable(this, getActionBar(), "titlebar_drawable"); //$NON-NLS-1$
1606 v = findViewById(R.id.navigation_statusbar);
1607 if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
1608 theme.setBackgroundDrawable(this, v, "titlebar_drawable"); //$NON-NLS-1$
1610 theme.setBackgroundDrawable(this, v, "statusbar_drawable"); //$NON-NLS-1$
1612 v = findViewById(R.id.ab_overflow);
1613 theme.setImageDrawable(this, (ImageView)v, "ab_overflow_drawable"); //$NON-NLS-1$
1614 v = findViewById(R.id.ab_actions);
1615 theme.setImageDrawable(this, (ImageView)v, "ab_actions_drawable"); //$NON-NLS-1$
1616 v = findViewById(R.id.ab_search);
1617 theme.setImageDrawable(this, (ImageView)v, "ab_search_drawable"); //$NON-NLS-1$
1618 v = findViewById(R.id.ab_bookmarks);
1619 theme.setImageDrawable(this, (ImageView)v, "ab_bookmarks_drawable"); //$NON-NLS-1$
1620 v = findViewById(R.id.ab_history);
1621 theme.setImageDrawable(this, (ImageView)v, "ab_history_drawable"); //$NON-NLS-1$
1623 v = findViewById(R.id.ab_configuration);
1624 theme.setImageDrawable(this, (ImageView)v, "expander_open_drawable"); //$NON-NLS-1$
1625 v = findViewById(R.id.ab_close);
1626 theme.setImageDrawable(this, (ImageView)v, "expander_close_drawable"); //$NON-NLS-1$
1627 v = findViewById(R.id.ab_sort_mode);
1628 theme.setImageDrawable(this, (ImageView)v, "ab_sort_mode_drawable"); //$NON-NLS-1$
1629 v = findViewById(R.id.ab_layout_mode);
1630 theme.setImageDrawable(this, (ImageView)v, "ab_layout_mode_drawable"); //$NON-NLS-1$
1631 v = findViewById(R.id.ab_view_options);
1632 theme.setImageDrawable(this, (ImageView)v, "ab_view_options_drawable"); //$NON-NLS-1$
1634 v = findViewById(R.id.navigation_selectionbar);
1635 theme.setBackgroundDrawable(this, v, "selectionbar_drawable"); //$NON-NLS-1$
1636 v = findViewById(R.id.ab_selection_done);
1637 theme.setImageDrawable(this, (ImageView)v, "ab_selection_done_drawable"); //$NON-NLS-1$
1638 v = findViewById(R.id.navigation_status_selection_label);
1639 theme.setTextColor(this, (TextView)v, "text_color"); //$NON-NLS-1$
1641 int cc = this.mNavigationViews.length;
1642 for (int i = 0; i < cc; i++) {
1643 getNavigationView(i).applyTheme();