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 exit
584 Log.e(TAG, getString(R.string.msgs_cant_create_console), ex);
585 // We don't have any console
586 // Show exception and exit
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();
616 // Show exception and exit
617 DialogHelper.showToast(
618 NavigationActivity.this,
619 R.string.msgs_cant_create_console, Toast.LENGTH_LONG);
625 //Ensure initial is an absolute directory
627 initialDir = new File(initialDir).getAbsolutePath();
628 } catch (Throwable e) {
629 Log.e(TAG, "Resolve of initital directory fails", e); //$NON-NLS-1$
632 R.string.msgs_settings_invalid_initial_directory,
634 DialogHelper.showToast(NavigationActivity.this, msg, Toast.LENGTH_SHORT);
635 initialDir = FileHelper.ROOT_DIRECTORY;
638 // Change the current directory to the preference initial directory or the
640 String navigateTo = getIntent().getStringExtra(EXTRA_NAVIGATE_TO);
641 if (navigateTo != null && navigateTo.length() > 0) {
642 navigationView.changeCurrentDir(navigateTo);
644 navigationView.changeCurrentDir(initialDir);
652 * Method that verifies the intent passed to the activity, and checks
653 * if a request is made like Search.
655 * @param intent The intent to check
658 void checkIntent(Intent intent) {
660 if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
661 Intent searchIntent = new Intent(this, SearchActivity.class);
662 searchIntent.setAction(Intent.ACTION_SEARCH);
663 //- SearchActivity.EXTRA_SEARCH_DIRECTORY
664 searchIntent.putExtra(
665 SearchActivity.EXTRA_SEARCH_DIRECTORY,
666 getCurrentNavigationView().getCurrentDir());
667 //- SearchManager.APP_DATA
668 if (intent.getBundleExtra(SearchManager.APP_DATA) != null) {
669 Bundle bundle = new Bundle();
670 bundle.putAll(intent.getBundleExtra(SearchManager.APP_DATA));
671 searchIntent.putExtra(SearchManager.APP_DATA, bundle);
673 //-- SearchManager.QUERY
674 String query = intent.getStringExtra(SearchManager.QUERY);
676 searchIntent.putExtra(SearchManager.QUERY, query);
678 //- android.speech.RecognizerIntent.EXTRA_RESULTS
679 ArrayList<String> extraResults =
680 intent.getStringArrayListExtra(android.speech.RecognizerIntent.EXTRA_RESULTS);
681 if (extraResults != null) {
682 searchIntent.putStringArrayListExtra(
683 android.speech.RecognizerIntent.EXTRA_RESULTS, extraResults);
685 startActivityForResult(searchIntent, INTENT_REQUEST_SEARCH);
689 // Navigate to the requested path
690 String navigateTo = intent.getStringExtra(EXTRA_NAVIGATE_TO);
691 if (navigateTo != null && navigateTo.length() >= 0) {
692 getCurrentNavigationView().changeCurrentDir(navigateTo);
700 public boolean onKeyUp(int keyCode, KeyEvent event) {
701 if (keyCode == KeyEvent.KEYCODE_MENU) {
702 showOverflowPopUp(this.mOptionsAnchorView);
705 if (keyCode == KeyEvent.KEYCODE_BACK) {
706 if (checkBackAction()) {
710 // An exit event has occurred, force the destroy the consoles
713 return super.onKeyUp(keyCode, event);
720 public boolean onOptionsItemSelected(MenuItem item) {
721 switch (item.getItemId()) {
722 case android.R.id.home:
723 if ((getActionBar().getDisplayOptions() & ActionBar.DISPLAY_HOME_AS_UP)
724 == ActionBar.DISPLAY_HOME_AS_UP) {
729 return super.onOptionsItemSelected(item);
734 * Method invoked when an action item is clicked.
736 * @param view The button pushed
738 public void onActionBarItemClick(View view) {
739 switch (view.getId()) {
740 //######################
741 //Navigation Custom Title
742 //######################
743 case R.id.ab_configuration:
744 //Show navigation view configuration toolbar
745 getCurrentNavigationView().getCustomTitle().showConfigurationView();
746 getActionBar().setDisplayHomeAsUpEnabled(true);
747 getActionBar().setHomeButtonEnabled(true);
750 //Hide navigation view configuration toolbar
751 getCurrentNavigationView().getCustomTitle().hideConfigurationView();
754 //######################
756 //######################
757 case R.id.ab_filesystem_info:
758 //Show information of the filesystem
759 MountPoint mp = getCurrentNavigationView().getBreadcrumb().getMountPointInfo();
760 DiskUsage du = getCurrentNavigationView().getBreadcrumb().getDiskUsageInfo();
761 showMountPointInfo(mp, du);
764 //######################
765 //Navigation view options
766 //######################
767 case R.id.ab_sort_mode:
768 showSettingsPopUp(view,
770 new FileManagerSettings[]{
771 FileManagerSettings.SETTINGS_SORT_MODE}));
773 case R.id.ab_layout_mode:
774 showSettingsPopUp(view,
776 new FileManagerSettings[]{
777 FileManagerSettings.SETTINGS_LAYOUT_MODE}));
779 case R.id.ab_view_options:
780 // If we are in ChRooted mode, then don't show non-secure items
781 if (this.mChRooted) {
782 showSettingsPopUp(view,
783 Arrays.asList(new FileManagerSettings[]{
784 FileManagerSettings.SETTINGS_SHOW_DIRS_FIRST}));
786 showSettingsPopUp(view,
787 Arrays.asList(new FileManagerSettings[]{
788 FileManagerSettings.SETTINGS_SHOW_DIRS_FIRST,
789 FileManagerSettings.SETTINGS_SHOW_HIDDEN,
790 FileManagerSettings.SETTINGS_SHOW_SYSTEM,
791 FileManagerSettings.SETTINGS_SHOW_SYMLINKS}));
796 //######################
798 //######################
799 case R.id.ab_selection_done:
800 //Show information of the filesystem
801 getCurrentNavigationView().onDeselectAll();
804 //######################
806 //######################
807 case R.id.ab_actions:
808 openActionsDialog(getCurrentNavigationView().getCurrentDir(), true);
811 case R.id.ab_bookmarks:
815 case R.id.ab_history:
823 case R.id.ab_overflow:
824 showOverflowPopUp(view);
836 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
838 switch (requestCode) {
839 case INTENT_REQUEST_BOOKMARK:
840 if (resultCode == RESULT_OK) {
841 FileSystemObject fso =
842 (FileSystemObject)data.
843 getSerializableExtra(EXTRA_BOOKMARK_SELECTION);
846 getCurrentNavigationView().open(fso);
851 case INTENT_REQUEST_HISTORY:
852 if (resultCode == RESULT_OK) {
853 //Change current directory
855 (History)data.getSerializableExtra(EXTRA_HISTORY_ENTRY_SELECTION);
856 navigateToHistory(history);
857 } else if (resultCode == RESULT_CANCELED) {
858 boolean clear = data.getBooleanExtra(EXTRA_HISTORY_CLEAR, false);
865 case INTENT_REQUEST_SEARCH:
866 if (resultCode == RESULT_OK) {
868 FileSystemObject fso =
869 (FileSystemObject)data.
870 getSerializableExtra(EXTRA_SEARCH_ENTRY_SELECTION);
871 SearchInfoParcelable searchInfo =
872 data.getParcelableExtra(EXTRA_SEARCH_LAST_SEARCH_DATA);
874 //Goto to new directory
875 getCurrentNavigationView().open(fso, searchInfo);
877 } else if (resultCode == RESULT_CANCELED) {
878 SearchInfoParcelable searchInfo =
879 data.getParcelableExtra(EXTRA_SEARCH_LAST_SEARCH_DATA);
880 if (searchInfo != null && searchInfo.isSuccessNavigation()) {
881 //Navigate to previous history
884 // I don't know is the search view was changed, so try to do a refresh
885 // of the navigation view
886 getCurrentNavigationView().refresh(true);
901 public void onNewHistory(HistoryNavigable navigable) {
902 //Recollect information about current status
903 History history = new History(this.mHistory.size(), navigable);
904 this.mHistory.add(history);
905 getActionBar().setDisplayHomeAsUpEnabled(true);
906 getActionBar().setHomeButtonEnabled(true);
913 public void onCheckHistory() {
914 //Need to show HomeUp Button
915 boolean enabled = this.mHistory != null && this.mHistory.size() > 0;
916 getActionBar().setDisplayHomeAsUpEnabled(enabled);
917 getActionBar().setHomeButtonEnabled(enabled);
924 public void onRequestRefresh(Object o, boolean clearSelection) {
925 if (o instanceof FileSystemObject) {
926 // Refresh only the item
927 this.getCurrentNavigationView().refresh((FileSystemObject)o);
928 } else if (o == null) {
930 getCurrentNavigationView().refresh();
932 if (clearSelection) {
933 this.getCurrentNavigationView().onDeselectAll();
941 public void onRequestRemove(Object o, boolean clearSelection) {
942 if (o instanceof FileSystemObject) {
944 this.getCurrentNavigationView().removeItem((FileSystemObject)o);
946 //Remove from history
947 removeFromHistory((FileSystemObject)o);
949 onRequestRefresh(null, clearSelection);
951 if (clearSelection) {
952 this.getCurrentNavigationView().onDeselectAll();
960 public void onNavigateTo(Object o) {
968 public void onSelectionChanged(NavigationView navView, List<FileSystemObject> selectedItems) {
969 this.mSelectionBar.setSelection(selectedItems);
976 public void onRequestMenu(NavigationView navView, FileSystemObject item) {
977 // Show the actions dialog
978 openActionsDialog(item, false);
982 * Method that shows a popup with a menu associated a {@link FileManagerSettings}.
984 * @param anchor The action button that was pressed
985 * @param settings The array of settings associated with the action button
987 private void showSettingsPopUp(View anchor, List<FileManagerSettings> settings) {
989 final MenuSettingsAdapter adapter = new MenuSettingsAdapter(this, settings);
991 //Create a show the popup menu
992 final ListPopupWindow popup = DialogHelper.createListPopupWindow(this, adapter, anchor);
993 popup.setOnItemClickListener(new OnItemClickListener() {
995 public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
996 FileManagerSettings setting =
997 ((MenuSettingsAdapter)parent.getAdapter()).getSetting(position);
998 final int value = ((MenuSettingsAdapter)parent.getAdapter()).getId(position);
1001 if (setting.compareTo(FileManagerSettings.SETTINGS_LAYOUT_MODE) == 0) {
1002 //Need to change the layout
1003 getCurrentNavigationView().changeViewMode(
1004 NavigationLayoutMode.fromId(value));
1007 if (setting.getDefaultValue() instanceof Enum<?>) {
1009 Preferences.savePreference(setting, new ObjectIdentifier() {
1011 public int getId() {
1018 Preferences.getSharedPreferences().
1021 ((Boolean)setting.getDefaultValue()).booleanValue());
1022 Preferences.savePreference(setting, Boolean.valueOf(!newval), false);
1024 getCurrentNavigationView().refresh();
1026 } catch (Exception e) {
1027 Log.e(TAG, "Error applying navigation option", e); //$NON-NLS-1$
1028 NavigationActivity.this.mHandler.post(new Runnable() {
1031 DialogHelper.showToast(
1032 NavigationActivity.this,
1033 R.string.msgs_settings_save_failure, Toast.LENGTH_SHORT);
1039 getCurrentNavigationView().getCustomTitle().restoreView();
1044 popup.setOnDismissListener(new PopupWindow.OnDismissListener() {
1046 public void onDismiss() {
1054 * Method that shows a popup with the activity main menu.
1056 * @param anchor The action button that was pressed
1058 private void showOverflowPopUp(View anchor) {
1059 SimpleMenuListAdapter adapter =
1060 new HighlightedSimpleMenuListAdapter(this, R.menu.navigation);
1061 Menu menu = adapter.getMenu();
1062 int cc = this.mActionBar.getChildCount();
1063 for (int i = 0, j = this.mActionBar.getChildCount() - 1; i < cc; i++, j--) {
1064 View child = this.mActionBar.getChildAt(i);
1065 boolean visible = child.getVisibility() == View.VISIBLE;
1067 menu.removeItem(menu.getItem(j).getItemId());
1071 final ListPopupWindow popup = DialogHelper.createListPopupWindow(this, adapter, anchor);
1072 popup.setOnItemClickListener(new OnItemClickListener() {
1074 public void onItemClick(
1075 final AdapterView<?> parent, final View v, final int position, final long id) {
1077 final int itemId = (int)id;
1078 NavigationActivity.this.mHandler.post(new Runnable() {
1083 case R.id.mnu_settings:
1085 Intent settings = new Intent(
1086 NavigationActivity.this, SettingsPreferences.class);
1087 startActivity(settings);
1090 case R.id.mnu_history:
1096 case R.id.mnu_bookmarks:
1102 case R.id.mnu_search:
1118 * Method that show the information of a filesystem mount point.
1120 * @param mp The mount point info
1121 * @param du The disk usage of the mount point
1123 private void showMountPointInfo(MountPoint mp, DiskUsage du) {
1124 //Has mount point info?
1126 //There is no information
1128 DialogHelper.createWarningDialog(
1130 R.string.filesystem_info_warning_title,
1131 R.string.filesystem_info_warning_msg);
1132 DialogHelper.delegateDialogShow(this, alert);
1136 //Show a the filesystem info dialog
1137 FilesystemInfoDialog dialog = new FilesystemInfoDialog(this, mp, du);
1138 dialog.setOnMountListener(new OnMountListener() {
1140 public void onRemount(MountPoint mountPoint) {
1141 //Update the statistics of breadcrumb, only if mount point is the same
1142 Breadcrumb breadcrumb = getCurrentNavigationView().getBreadcrumb();
1143 if (breadcrumb.getMountPointInfo().compareTo(mountPoint) == 0) {
1144 breadcrumb.updateMountPointInfo();
1152 * Method that checks the action that must be realized when the
1153 * back button is pushed.
1155 * @return boolean Indicates if the action must be intercepted
1157 private boolean checkBackAction() {
1158 // We need a basic structure to check this
1159 if (getCurrentNavigationView() == null) return false;
1161 //Check if the configuration view is showing. In this case back
1162 //action must be "close configuration"
1163 if (getCurrentNavigationView().getCustomTitle().isConfigurationViewShowing()) {
1164 getCurrentNavigationView().getCustomTitle().restoreView();
1168 //Do back operation over the navigation history
1169 boolean flag = this.mExitFlag;
1171 this.mExitFlag = !back();
1173 // Retrieve if the exit status timeout has expired
1174 long now = System.currentTimeMillis();
1175 boolean timeout = (this.mExitBackTimeout == -1 ||
1176 (now - this.mExitBackTimeout) > RELEASE_EXIT_CHECK_TIMEOUT);
1178 //Check if there no history and if the user was advised in the last back action
1179 if (this.mExitFlag && (this.mExitFlag != flag || timeout)) {
1180 //Communicate the user that the next time the application will be closed
1181 this.mExitBackTimeout = System.currentTimeMillis();
1182 DialogHelper.showToast(this, R.string.msgs_push_again_to_exit, Toast.LENGTH_SHORT);
1186 //Back action not applied
1187 return !this.mExitFlag;
1194 public boolean onSearchRequested() {
1195 Bundle bundle = new Bundle();
1197 SearchActivity.EXTRA_SEARCH_DIRECTORY,
1198 getCurrentNavigationView().getCurrentDir());
1199 startSearch(Preferences.getLastSearch(), true, bundle, false);
1204 * Method that returns the history size.
1206 private void clearHistory() {
1207 this.mHistory.clear();
1212 * Method that navigates to the passed history reference.
1214 * @param history The history reference
1215 * @return boolean A problem occurs while navigate
1217 public boolean navigateToHistory(History history) {
1220 History realHistory = this.mHistory.get(history.getPosition());
1222 //Navigate to item. Check what kind of history is
1223 if (realHistory.getItem() instanceof NavigationViewInfoParcelable) {
1225 NavigationViewInfoParcelable info =
1226 (NavigationViewInfoParcelable)realHistory.getItem();
1227 int viewId = info.getId();
1228 NavigationView view = getNavigationView(viewId);
1229 // Selected items must not be restored from on history navigation
1230 info.setSelectedFiles(view.getSelectedFiles());
1231 view.onRestoreState(info);
1233 } else if (realHistory.getItem() instanceof SearchInfoParcelable) {
1234 //Search (open search with the search results)
1235 SearchInfoParcelable info = (SearchInfoParcelable)realHistory.getItem();
1236 Intent searchIntent = new Intent(this, SearchActivity.class);
1237 searchIntent.setAction(SearchActivity.ACTION_RESTORE);
1238 searchIntent.putExtra(SearchActivity.EXTRA_SEARCH_RESTORE, (Parcelable)info);
1239 startActivityForResult(searchIntent, INTENT_REQUEST_SEARCH);
1241 //The type is unknown
1242 throw new IllegalArgumentException("Unknown history type"); //$NON-NLS-1$
1245 //Remove the old history
1246 int cc = realHistory.getPosition();
1247 for (int i = this.mHistory.size() - 1; i >= cc; i--) {
1248 this.mHistory.remove(i);
1250 if (this.mHistory.size() == 0) {
1251 getActionBar().setDisplayHomeAsUpEnabled(false);
1252 getActionBar().setHomeButtonEnabled(false);
1258 } catch (Throwable ex) {
1259 if (history != null) {
1261 String.format("Failed to navigate to history %d: %s", //$NON-NLS-1$
1262 Integer.valueOf(history.getPosition()),
1263 history.getItem().getTitle()), ex);
1266 String.format("Failed to navigate to history: null", ex)); //$NON-NLS-1$
1268 this.mHandler.post(new Runnable() {
1271 DialogHelper.showToast(
1272 NavigationActivity.this,
1273 R.string.msgs_history_unknown, Toast.LENGTH_LONG);
1277 //Not change directory
1283 * Method that request a back action over the navigation history.
1285 * @return boolean If a back action was applied
1287 public boolean back() {
1288 // Check that has valid history
1289 while (this.mHistory.size() > 0) {
1290 History h = this.mHistory.get(this.mHistory.size() - 1);
1291 if (h.getItem() instanceof NavigationViewInfoParcelable) {
1292 // Verify that the path exists
1293 String path = ((NavigationViewInfoParcelable)h.getItem()).getCurrentDir();
1296 FileSystemObject info = CommandHelper.getFileInfo(this, path, null);
1300 this.mHistory.remove(this.mHistory.size() - 1);
1301 } catch (Exception e) {
1302 ExceptionUtil.translateException(this, e, true, false);
1303 this.mHistory.remove(this.mHistory.size() - 1);
1310 //Extract a history from the
1311 if (this.mHistory.size() > 0) {
1312 //Navigate to history
1313 return navigateToHistory(this.mHistory.get(this.mHistory.size() - 1));
1321 * Method that opens the actions dialog
1323 * @param item The path or the {@link FileSystemObject}
1324 * @param global If the menu to display is the one with global actions
1326 private void openActionsDialog(Object item, boolean global) {
1327 // Resolve the full path
1328 String path = String.valueOf(item);
1329 if (item instanceof FileSystemObject) {
1330 path = ((FileSystemObject)item).getFullPath();
1333 // Prior to show the dialog, refresh the item reference
1334 FileSystemObject fso = null;
1336 fso = CommandHelper.getFileInfo(this, path, false, null);
1338 throw new NoSuchFileOrDirectory(path);
1341 } catch (Exception e) {
1343 ExceptionUtil.translateException(this, e);
1345 // Remove the object
1346 if (e instanceof FileNotFoundException || e instanceof NoSuchFileOrDirectory) {
1347 // If have a FileSystemObject reference then there is no need to search
1348 // the path (less resources used)
1349 if (item instanceof FileSystemObject) {
1350 getCurrentNavigationView().removeItem((FileSystemObject)item);
1352 getCurrentNavigationView().removeItem((String)item);
1359 ActionsDialog dialog = new ActionsDialog(this, fso, global, false);
1360 dialog.setOnRequestRefreshListener(this);
1361 dialog.setOnSelectionListener(getCurrentNavigationView());
1366 * Method that opens the bookmarks activity.
1369 void openBookmarks() {
1370 Intent bookmarksIntent = new Intent(this, BookmarksActivity.class);
1371 bookmarksIntent.addFlags(Intent.FLAG_ACTIVITY_TASK_ON_HOME);
1372 startActivityForResult(bookmarksIntent, INTENT_REQUEST_BOOKMARK);
1376 * Method that opens the history activity.
1379 void openHistory() {
1380 Intent historyIntent = new Intent(this, HistoryActivity.class);
1381 historyIntent.putExtra(HistoryActivity.EXTRA_HISTORY_LIST, (Serializable)this.mHistory);
1382 historyIntent.addFlags(Intent.FLAG_ACTIVITY_TASK_ON_HOME);
1383 startActivityForResult(historyIntent, INTENT_REQUEST_HISTORY);
1387 * Method that opens the search activity.
1391 onSearchRequested();
1395 * Method that remove the {@link FileSystemObject} from the history
1397 private void removeFromHistory(FileSystemObject fso) {
1398 if (this.mHistory != null) {
1399 int cc = this.mHistory.size();
1400 for (int i = cc-1; i >= 0 ; i--) {
1401 History history = this.mHistory.get(i);
1402 if (history.getItem() instanceof NavigationViewInfoParcelable) {
1403 String p0 = fso.getFullPath();
1405 ((NavigationViewInfoParcelable)history.getItem()).getCurrentDir();
1406 if (p0.compareTo(p1) == 0) {
1407 this.mHistory.remove(i);
1415 * Method that ask the user to change the access mode prior to crash.
1419 //Show a dialog asking the user
1420 AlertDialog dialog =
1421 DialogHelper.createYesNoDialog(
1423 R.string.msgs_change_to_prompt_access_mode_title,
1424 R.string.msgs_change_to_prompt_access_mode_msg,
1425 new DialogInterface.OnClickListener() {
1427 public void onClick(DialogInterface alertDialog, int which) {
1428 if (which == DialogInterface.BUTTON_NEGATIVE) {
1429 // We don't have any console
1430 // Show exception and exit
1431 DialogHelper.showToast(
1432 NavigationActivity.this,
1433 R.string.msgs_cant_create_console, Toast.LENGTH_LONG);
1438 // Ok. Now try to change to prompt mode. Any crash
1439 // here is a fatal error. We won't have any console to operate.
1442 ConsoleBuilder.changeToNonPrivilegedConsole(NavigationActivity.this);
1445 Preferences.savePreference(
1446 FileManagerSettings.SETTINGS_ACCESS_MODE,
1447 AccessMode.PROMPT, true);
1449 } catch (Exception e) {
1450 // Displays an exception and exit
1451 Log.e(TAG, getString(R.string.msgs_cant_create_console), e);
1452 DialogHelper.showToast(
1453 NavigationActivity.this,
1454 R.string.msgs_cant_create_console, Toast.LENGTH_LONG);
1459 DialogHelper.delegateDialogShow(this, dialog);
1463 * Method that creates a ChRooted environment, protecting the user to break anything in
1467 void createChRooted() {
1468 // If we are in a ChRooted mode, then do nothing
1469 if (this.mChRooted) return;
1470 this.mChRooted = true;
1472 int cc = this.mNavigationViews.length;
1473 for (int i = 0; i < cc; i++) {
1474 this.mNavigationViews[i].createChRooted();
1477 // Remove the selection
1478 cc = this.mNavigationViews.length;
1479 for (int i = 0; i < cc; i++) {
1480 getCurrentNavigationView().onDeselectAll();
1483 // Remove the history (don't allow to access to previous data)
1488 * Method that exits from a ChRooted
1491 void exitChRooted() {
1492 // If we aren't in a ChRooted mode, then do nothing
1493 if (!this.mChRooted) return;
1494 this.mChRooted = false;
1496 int cc = this.mNavigationViews.length;
1497 for (int i = 0; i < cc; i++) {
1498 this.mNavigationViews[i].exitChRooted();
1503 * Method called when a controlled exit is required
1508 FileManagerApplication.destroyBackgroundConsole();
1509 } catch (Throwable ex) {
1513 ConsoleBuilder.destroyConsole();
1514 } catch (Throwable ex) {
1521 * Method that reconfigures the layout for better fit in portrait and landscape modes
1523 private void onLayoutChanged() {
1524 Theme theme = ThemeManager.getCurrentTheme(this);
1526 // Apply only when the orientation was changed
1527 int orientation = getResources().getConfiguration().orientation;
1528 if (this.mOrientation == orientation) return;
1529 this.mOrientation = orientation;
1531 if (this.mOrientation == Configuration.ORIENTATION_LANDSCAPE) {
1533 ViewGroup statusBar = (ViewGroup)findViewById(R.id.navigation_statusbar);
1534 if (statusBar.getParent() != null) {
1535 ViewGroup parent = (ViewGroup) statusBar.getParent();
1536 parent.removeView(statusBar);
1539 // Calculate the action button size (all the buttons must fit in the title bar)
1540 int bw = (int)getResources().getDimension(R.dimen.default_buttom_width);
1541 int abw = this.mActionBar.getChildCount() * bw;
1543 int cc = statusBar.getChildCount();
1544 for (int i = 0; i < cc; i++) {
1545 View child = statusBar.getChildAt(i);
1546 if (child instanceof ButtonItem) {
1551 boolean showOptionsMenu = AndroidHelper.showOptionsMenu(getApplicationContext());
1552 if (!showOptionsMenu) {
1556 // Add to the new location
1557 ViewGroup newParent = (ViewGroup)findViewById(R.id.navigation_title_landscape_holder);
1558 LinearLayout.LayoutParams params =
1559 new LinearLayout.LayoutParams(
1561 ViewGroup.LayoutParams.MATCH_PARENT);
1562 statusBar.setLayoutParams(params);
1563 newParent.addView(statusBar);
1566 theme.setBackgroundDrawable(this, statusBar, "titlebar_drawable"); //$NON-NLS-1$
1569 View holder = findViewById(R.id.navigation_statusbar_portrait_holder);
1570 holder.setVisibility(View.GONE);
1574 ViewGroup statusBar = (ViewGroup)findViewById(R.id.navigation_statusbar);
1575 if (statusBar.getParent() != null) {
1576 ViewGroup parent = (ViewGroup) statusBar.getParent();
1577 parent.removeView(statusBar);
1580 // Add to the new location
1581 ViewGroup newParent = (ViewGroup)findViewById(
1582 R.id.navigation_statusbar_portrait_holder);
1583 LinearLayout.LayoutParams params =
1584 new LinearLayout.LayoutParams(
1585 ViewGroup.LayoutParams.MATCH_PARENT,
1586 ViewGroup.LayoutParams.MATCH_PARENT);
1587 statusBar.setLayoutParams(params);
1588 newParent.addView(statusBar);
1591 theme.setBackgroundDrawable(this, statusBar, "statusbar_drawable"); //$NON-NLS-1$
1594 newParent.setVisibility(View.VISIBLE);
1599 * Method that applies the current theme to the activity
1603 int orientation = getResources().getConfiguration().orientation;
1604 Theme theme = ThemeManager.getCurrentTheme(this);
1605 theme.setBaseTheme(this, false);
1608 View v = findViewById(R.id.navigation_layout);
1609 theme.setBackgroundDrawable(this, v, "background_drawable"); //$NON-NLS-1$
1611 theme.setTitlebarDrawable(this, getActionBar(), "titlebar_drawable"); //$NON-NLS-1$
1613 v = findViewById(R.id.navigation_statusbar);
1614 if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
1615 theme.setBackgroundDrawable(this, v, "titlebar_drawable"); //$NON-NLS-1$
1617 theme.setBackgroundDrawable(this, v, "statusbar_drawable"); //$NON-NLS-1$
1619 v = findViewById(R.id.ab_overflow);
1620 theme.setImageDrawable(this, (ImageView)v, "ab_overflow_drawable"); //$NON-NLS-1$
1621 v = findViewById(R.id.ab_actions);
1622 theme.setImageDrawable(this, (ImageView)v, "ab_actions_drawable"); //$NON-NLS-1$
1623 v = findViewById(R.id.ab_search);
1624 theme.setImageDrawable(this, (ImageView)v, "ab_search_drawable"); //$NON-NLS-1$
1625 v = findViewById(R.id.ab_bookmarks);
1626 theme.setImageDrawable(this, (ImageView)v, "ab_bookmarks_drawable"); //$NON-NLS-1$
1627 v = findViewById(R.id.ab_history);
1628 theme.setImageDrawable(this, (ImageView)v, "ab_history_drawable"); //$NON-NLS-1$
1630 v = findViewById(R.id.ab_configuration);
1631 theme.setImageDrawable(this, (ImageView)v, "expander_open_drawable"); //$NON-NLS-1$
1632 v = findViewById(R.id.ab_close);
1633 theme.setImageDrawable(this, (ImageView)v, "expander_close_drawable"); //$NON-NLS-1$
1634 v = findViewById(R.id.ab_sort_mode);
1635 theme.setImageDrawable(this, (ImageView)v, "ab_sort_mode_drawable"); //$NON-NLS-1$
1636 v = findViewById(R.id.ab_layout_mode);
1637 theme.setImageDrawable(this, (ImageView)v, "ab_layout_mode_drawable"); //$NON-NLS-1$
1638 v = findViewById(R.id.ab_view_options);
1639 theme.setImageDrawable(this, (ImageView)v, "ab_view_options_drawable"); //$NON-NLS-1$
1641 v = findViewById(R.id.navigation_selectionbar);
1642 theme.setBackgroundDrawable(this, v, "selectionbar_drawable"); //$NON-NLS-1$
1643 v = findViewById(R.id.ab_selection_done);
1644 theme.setImageDrawable(this, (ImageView)v, "ab_selection_done_drawable"); //$NON-NLS-1$
1645 v = findViewById(R.id.navigation_status_selection_label);
1646 theme.setTextColor(this, (TextView)v, "text_color"); //$NON-NLS-1$
1648 int cc = this.mNavigationViews.length;
1649 for (int i = 0; i < cc; i++) {
1650 getNavigationView(i).applyTheme();