Android Open Source - Todo Todo Location Preference






From Project

Back to project page Todo.

License

The source code is released under:

GNU General Public License

If you think the Android project Todo listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/**
 * This file is part of Todo.txt for Android, an app for managing your todo.txt file (http://todotxt.com).
 */*w  w w  .ja  va 2s  . com*/
 * Copyright (c) 2009-2013 Todo.txt for Android contributors (http://todotxt.com)
 *
 * LICENSE:
 *
 * Todo.txt for Android is free software: you can redistribute it and/or modify it under the terms of the GNU General
 * Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any
 * later version.
 *
 * Todo.txt for Android is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the 
 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with Todo.txt for Android. If not, see
 * <http://www.gnu.org/licenses/>.
 *
 * Todo.txt for Android's source code is available at https://github.com/ginatrapani/todo.txt-android
 *
 * @author Todo.txt for Android contributors <todotxt@yahoogroups.com>
 * @license http://www.gnu.org/licenses/gpl.html
 * @copyright 2009-2013 Todo.txt for Android contributors (http://todotxt.com)
 */

package com.todotxt.todotxttouch;

import android.app.AlertDialog.Builder;
import android.app.Dialog;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.os.AsyncTask;
import android.os.Parcel;
import android.os.Parcelable;
import android.preference.DialogPreference;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.style.ForegroundColorSpan;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import com.todotxt.todotxttouch.remote.RemoteFolder;
import com.todotxt.todotxttouch.remote.RemoteFolderImpl;
import com.todotxt.todotxttouch.util.Tree;
import java.io.File;
import java.util.Collections;
import java.util.List;

public class TodoLocationPreference extends DialogPreference {
  final static String TAG = TodoLocationPreference.class.getSimpleName();
  private TodoApplication mApp;
  private DisplayMode mDisplayMode = DisplayMode.NORMAL;
  private boolean mDisplayWarning = false;
  private ArrayAdapter<String> mAdapter;
  private String mInitialPath;
  private Tree<RemoteFolder> mRootFolder;
  private Tree<RemoteFolder> mCurrentSelection;
  private ListView mListView;
  private View mEmptyView;
  private View mListFrame;
  private EditText mEditText;
  private TextView mCurrentFolderTextView;
  public TodoLocationPreference(Context context, AttributeSet attrs) {
    super(context, attrs);

    setDialogLayoutResource(R.layout.todo_location_dialog);
  }

  @Override
  protected Object onGetDefaultValue(TypedArray a, int index) {
    return a.getString(index);
  }

  @Override
  protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
    if (mInitialPath == null) {
      mInitialPath = restoreValue ? getPersistedString(null)
        : (String) defaultValue;
    }
  }

  @Override
  protected void onPrepareDialogBuilder(Builder builder) {
    // Display the warning message if necessary.
    // Otherwise, just use the default layout.
    if (mDisplayMode == DisplayMode.WARNING) {
      builder.setMessage(getWarningMessage());
      builder.setPositiveButton(R.string.todo_path_warning_override, this);
    } else {
      // nothing to do here...
    }
  }

  private CharSequence getWarningMessage() {
    SpannableString ss = new SpannableString(getContext().getString(
      R.string.todo_path_warning
    )
    );
    ss.setSpan(new ForegroundColorSpan(Color.RED), 0, ss.length(),
      Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
    );

    return ss;
  }

  @Override
  protected void onClick() {
    // Called when the preference is clicked
    // This method displays the dialog.
    // When mDisplayWarning is set, we want to display
    // a warning message instead of the actual dialog
    mDisplayMode = mDisplayWarning ? DisplayMode.WARNING : DisplayMode.NORMAL;

    super.onClick();
  }

  @Override
  protected View onCreateDialogView() {
    if (mDisplayMode == DisplayMode.WARNING) {
      return null;
    }

    return super.onCreateDialogView();
  }

  @Override
  protected void onBindDialogView(View view) {
    super.onBindDialogView(view);

    mCurrentFolderTextView = (TextView) view.findViewById(R.id.folder_name);
    mListView = (ListView) view.findViewById(android.R.id.list);
    mEmptyView = view.findViewById(android.R.id.empty);
    mListFrame = view.findViewById(R.id.list_frame);
    mEditText = (EditText) view.findViewById(R.id.add_new);

    if (mDisplayMode == DisplayMode.ADD_NEW) {
      mEditText.setVisibility(View.VISIBLE);
      mListFrame.setVisibility(View.GONE);
    } else {
      mEditText.setVisibility(View.GONE);
      mListFrame.setVisibility(View.VISIBLE);
    }

    mAdapter = new ArrayAdapter<String>(getContext(), android.R.layout.simple_list_item_1);
    mListView.setAdapter(mAdapter);
    mListView.setEmptyView(mEmptyView);

    // initialize the view
    initFolderTree();
    selectFolder(mCurrentSelection);

    mListView.setOnItemClickListener(new OnItemClickListener() {
                                       public void onItemClick(AdapterView<?> parent, View view,
                                         int position, long id) {

                                         if (position == 0 && mCurrentSelection.getData().hasParent()) {
                                           // go back up to previous directory
                                           upToParent();
                                         } else if (position == mAdapter.getCount() - 1) {
                                           // signal that AddNew was clicked
                                           mDisplayMode = DisplayMode.ADD_NEW;
                                           mEditText.setVisibility(View.VISIBLE);
                                           mListFrame.setVisibility(View.GONE);
                                           mEditText.requestFocus();
                                         } else {
                                           // drill down to this directory
                                           int index = mCurrentSelection.getData().hasParent() ? position - 1
                                             : position;
                                           selectFolder(mCurrentSelection.getChild(index));
                                         }
                                       }
                                     }
    );
  }

  @Override
  protected void onDialogClosed(boolean positiveResult) {
    // If we are displaying the warning message and the user
    // clicked "I'm feeling dangerous", then redisplay the
    // dialog with the default layout
    if (mDisplayMode == DisplayMode.WARNING && positiveResult) {
      mDisplayMode = DisplayMode.NORMAL;
      showDialog(null);

      return;
    }

    if (mCurrentSelection != null && positiveResult) {
      String value = mCurrentSelection.getData().getPath();
      if (mDisplayMode == DisplayMode.ADD_NEW) {
        value = new File(value, mEditText.getText().toString())
          .toString();
        addNew(value);
      }

      if (callChangeListener(value)) {
        persistString(value);
      }
    }

    mInitialPath = null;
  }

  @Override
  protected Parcelable onSaveInstanceState() {
    final Parcelable superState = super.onSaveInstanceState();

    final SavedState myState = new SavedState(superState);
    myState.displayMode = mDisplayMode.name();

    if (mCurrentSelection != null) {
      myState.initialPath = mCurrentSelection.getData().getPath();
      // FIXME: need to save the entire tree.
    } else {
      myState.initialPath = mInitialPath;
    }

    return myState;
  }

  @Override
  protected void onRestoreInstanceState(Parcelable state) {
    if (state == null || !state.getClass().equals(SavedState.class)) {
      // Didn't save state for us in onSaveInstanceState
      super.onRestoreInstanceState(state);

      return;
    }

    SavedState myState = (SavedState) state;
    mDisplayMode = DisplayMode.valueOf(myState.displayMode);
    mInitialPath = myState.initialPath;
    super.onRestoreInstanceState(myState.getSuperState());
  }

  protected void showErrorMessage() {
    mEmptyView.findViewById(R.id.loading_spinner).setVisibility(View.GONE);
    mEmptyView.findViewById(R.id.empty_text).setVisibility(View.VISIBLE);
  }

  protected void showProgressIndicator() {
    mEmptyView.findViewById(R.id.empty_text).setVisibility(View.GONE);
    mEmptyView.findViewById(R.id.loading_spinner).setVisibility(View.VISIBLE);
  }

  public boolean shouldDisplayWarning() {
    return mDisplayWarning;
  }

  public void setDisplayWarning(boolean shouldDisplay) {
    mDisplayWarning = shouldDisplay;
  }

  public void setApplication(TodoApplication app) {
    mApp = app;
  }

  private void initFolderTree() {
    if (mRootFolder == null) {
      mRootFolder = mCurrentSelection = new Tree<RemoteFolder>(new RemoteFolderImpl(null, null, null, null));
    } else {
      // use initialPath to find the correct folder in the tree
      Tree<RemoteFolder> tree = findFolderInTree(mRootFolder, mInitialPath);

      if (tree != null) {
        mCurrentSelection = tree;
      }
    }
  }

  private Tree<RemoteFolder> findFolderInTree(Tree<RemoteFolder> tree, String path) {
    if (tree.getData().getPath().equalsIgnoreCase(path)) {
      return tree;
    }

    if (tree.isLoaded()) {
      for (Tree<RemoteFolder> child : tree.getChildren()) {
        Tree<RemoteFolder> res = findFolderInTree(child, path);

        if (res != null) {
          return res;
        }
      }
    }

    return null;
  }

  private void upToParent() {
    if (mCurrentSelection.getParent() != null) {
      selectFolder(mCurrentSelection.getParent());

      return;
    }

    // FIXME: Remove this.
    RemoteFolder parent = new RemoteFolderImpl(null, null, null, null);
    mRootFolder = new Tree<RemoteFolder>(parent);
    selectFolder(mRootFolder);
  }

  private void addNew(String path) {
    Tree<RemoteFolder> tree = findFolderInTree(mCurrentSelection, path);

    if (tree == null) {
      // FIXME: Remove this.
      RemoteFolder folder = new RemoteFolderImpl(null, null, null, null);
      tree = mCurrentSelection.addChild(folder);
    }

    setCurrentSelection(tree);
  }

  private void setCurrentSelection(Tree<RemoteFolder> folder) {
    mCurrentSelection = folder;
    mCurrentFolderTextView.setText(folder.getData().getName());
    populateListView(folder.getChildren());
  }

  private void selectFolder(Tree<RemoteFolder> folder) {
    if (!folder.isLoaded()) {
      getRemoteDirectoryListing(folder);
    } else {
      setCurrentSelection(folder);
    }
  }

  private void populateListView(List<Tree<RemoteFolder>> list) {
    mAdapter.clear();

    if (mCurrentSelection.getData().hasParent()) {
      mAdapter.add(getContext().getString(R.string.todo_path_prev_folder,
          mCurrentSelection.getData().getParentName()
        )
      );
    }

    if (list != null) {
      for (Tree<RemoteFolder> folder : list) {
        mAdapter.add(folder.getData().getName());
      }
    }

    mAdapter.add(getContext().getString(R.string.todo_path_add_new));
  }

  private void getRemoteDirectoryListing(final Tree<RemoteFolder> folder) {
    new AsyncTask<Void, Void, List<RemoteFolder>>() {
      @Override
      protected void onPreExecute() {
        showProgressIndicator();
        mAdapter.clear();
      }

      @Override
      protected List<RemoteFolder> doInBackground(Void... params) {
        try {

          // FIXME: Remove this.
          RemoteFolder parent = new RemoteFolderImpl(null, null, null, null);
          return Collections.singletonList(parent);
        } catch (Exception e) {
          Log.d(TAG, "failed to get remote folder list", e);
        }

        return null;
      }

      @Override
      protected void onPostExecute(List<RemoteFolder> result) {
        Dialog dialog = getDialog();

        if (dialog == null || !dialog.isShowing()) {
          return;
        }

        if (result == null) {
          showErrorMessage();

          return;
        }

        // if we are loading the parent of our current folder
        // add the current folder as a child so we can keep it's
        // children
        boolean shouldAddCurrent = mCurrentSelection.getData().getParentPath()
                                                    .equals(folder.getData().getPath());
        for (RemoteFolder child : result) {
          if (shouldAddCurrent && mCurrentSelection.getData().equals(child)) {
            folder.addChild(mCurrentSelection);
            shouldAddCurrent = false;
          } else {
            folder.addChild(child);
          }
        }

        if (shouldAddCurrent) {
          // if the user created the current folder,
          // it won't really exist yet, but let's not
          // wipe it out.
          folder.addChild(mCurrentSelection);
        }

        folder.setLoaded();
        setCurrentSelection(folder);
      }
    }.execute();
  }

  private static class SavedState extends BaseSavedState {
    @SuppressWarnings ("unused")
    public static final Creator<SavedState> CREATOR = new Creator<SavedState>() {
      public SavedState createFromParcel(Parcel in) {
        return new SavedState(in);
      }

      public SavedState[] newArray(int size) {
        return new SavedState[size];
      }
    };
    String displayMode;
    String initialPath;

    public SavedState(Parcel source) {
      super(source);
      displayMode = source.readString();
      initialPath = source.readString();
    }

    public SavedState(Parcelable superState) {
      super(superState);
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
      super.writeToParcel(dest, flags);
      dest.writeString(displayMode);
      dest.writeString(initialPath);
    }
  }

  enum DisplayMode {
    NORMAL, WARNING, ADD_NEW
  }
}




Java Source Code List

.MainActivity.java
com.todotxt.todotxttouch.AddTask.java
com.todotxt.todotxttouch.Constants.java
com.todotxt.todotxttouch.HelpActivity.java
com.todotxt.todotxttouch.PeriodicSyncStarter.java
com.todotxt.todotxttouch.Preferences.java
com.todotxt.todotxttouch.RelativeLayoutCheckable.java
com.todotxt.todotxttouch.SyncerService.java
com.todotxt.todotxttouch.TodoApplication.java
com.todotxt.todotxttouch.TodoException.java
com.todotxt.todotxttouch.TodoLocationPreference.java
com.todotxt.todotxttouch.TodoPreferences.java
com.todotxt.todotxttouch.TodoTxtTouch.java
com.todotxt.todotxttouch.TodoWidgetProvider.java
com.todotxt.todotxttouch.UpgradeHandler.java
com.todotxt.todotxttouch.remote.Client.java
com.todotxt.todotxttouch.remote.PullTodoResult.java
com.todotxt.todotxttouch.remote.RemoteClientManager.java
com.todotxt.todotxttouch.remote.RemoteClient.java
com.todotxt.todotxttouch.remote.RemoteConflictException.java
com.todotxt.todotxttouch.remote.RemoteException.java
com.todotxt.todotxttouch.remote.RemoteFolderImpl.java
com.todotxt.todotxttouch.remote.RemoteFolder.java
com.todotxt.todotxttouch.task.AndFilter.java
com.todotxt.todotxttouch.task.ByContextFilter.java
com.todotxt.todotxttouch.task.ByPriorityFilter.java
com.todotxt.todotxttouch.task.ByProjectFilter.java
com.todotxt.todotxttouch.task.ByTextFilter.java
com.todotxt.todotxttouch.task.ContextParser.java
com.todotxt.todotxttouch.task.EndpointsTaskBagImpl.java
com.todotxt.todotxttouch.task.FilterFactory.java
com.todotxt.todotxttouch.task.Filter.java
com.todotxt.todotxttouch.task.LinkParser.java
com.todotxt.todotxttouch.task.LocalFileTaskRepository.java
com.todotxt.todotxttouch.task.LocalTaskRepository.java
com.todotxt.todotxttouch.task.MailAddressParser.java
com.todotxt.todotxttouch.task.OrFilter.java
com.todotxt.todotxttouch.task.PhoneNumberParser.java
com.todotxt.todotxttouch.task.PriorityTextSplitter.java
com.todotxt.todotxttouch.task.Priority.java
com.todotxt.todotxttouch.task.ProjectParser.java
com.todotxt.todotxttouch.task.Sort.java
com.todotxt.todotxttouch.task.TaskBagFactory.java
com.todotxt.todotxttouch.task.TaskBagImpl.java
com.todotxt.todotxttouch.task.TaskBag.java
com.todotxt.todotxttouch.task.TaskPersistException.java
com.todotxt.todotxttouch.task.Task.java
com.todotxt.todotxttouch.task.TextSplitter.java
com.todotxt.todotxttouch.util.CursorPositionCalculator.java
com.todotxt.todotxttouch.util.Path.java
com.todotxt.todotxttouch.util.RelativeDate.java
com.todotxt.todotxttouch.util.Strings.java
com.todotxt.todotxttouch.util.TaskIo.java
com.todotxt.todotxttouch.util.Tree.java
com.todotxt.todotxttouch.util.Util.java
com.todotxt.todotxttouch.widget.ListWidgetProvider.java
com.todotxt.todotxttouch.widget.ListWidgetService.java
de.timroes.swipetodismiss.SwipeDismissList.java
uk.co.senab.actionbarpulltorefresh.extras.actionbarsherlock.AbsDefaultHeaderTransformer.java
uk.co.senab.actionbarpulltorefresh.extras.actionbarsherlock.PullToRefreshAttacher.java
uk.co.senab.actionbarpulltorefresh.library.DefaultHeaderTransformer.java
uk.co.senab.actionbarpulltorefresh.library.InstanceCreationUtils.java
uk.co.senab.actionbarpulltorefresh.library.PullToRefreshAttacher.java
uk.co.senab.actionbarpulltorefresh.library.PullToRefreshLayout.java
uk.co.senab.actionbarpulltorefresh.library.viewdelegates.AbsListViewDelegate.java
uk.co.senab.actionbarpulltorefresh.library.viewdelegates.ScrollYDelegate.java
uk.co.senab.actionbarpulltorefresh.library.viewdelegates.WebViewDelegate.java
voodsingular.todo.MyEndpointEndpoint.java
voodsingular.todo.MyEndpoint.java
voodsingular.todo.TaskBean.java