Home | History | Annotate | Download | only in documentsui
      1 /*
      2  * Copyright (C) 2013 The Android Open Source Project
      3  *
      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
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     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.
     15  */
     16 
     17 package com.android.documentsui;
     18 
     19 import android.app.Fragment;
     20 import android.app.FragmentManager;
     21 import android.app.FragmentTransaction;
     22 import android.content.Context;
     23 import android.os.Bundle;
     24 import android.text.Editable;
     25 import android.text.TextUtils;
     26 import android.text.TextWatcher;
     27 import android.view.KeyEvent;
     28 import android.view.LayoutInflater;
     29 import android.view.View;
     30 import android.view.ViewGroup;
     31 import android.widget.Button;
     32 import android.widget.EditText;
     33 import android.widget.ImageView;
     34 import android.widget.ProgressBar;
     35 
     36 import com.android.documentsui.model.DocumentInfo;
     37 
     38 /**
     39  * Display document title editor and save button.
     40  */
     41 public class SaveFragment extends Fragment {
     42     public static final String TAG = "SaveFragment";
     43 
     44     private DocumentInfo mReplaceTarget;
     45     private EditText mDisplayName;
     46     private Button mSave;
     47     private ProgressBar mProgress;
     48     private boolean mIgnoreNextEdit;
     49 
     50     private static final String EXTRA_MIME_TYPE = "mime_type";
     51     private static final String EXTRA_DISPLAY_NAME = "display_name";
     52 
     53     public static void show(FragmentManager fm, String mimeType, String displayName) {
     54         final Bundle args = new Bundle();
     55         args.putString(EXTRA_MIME_TYPE, mimeType);
     56         args.putString(EXTRA_DISPLAY_NAME, displayName);
     57 
     58         final SaveFragment fragment = new SaveFragment();
     59         fragment.setArguments(args);
     60 
     61         final FragmentTransaction ft = fm.beginTransaction();
     62         ft.replace(R.id.container_save, fragment, TAG);
     63         ft.commitAllowingStateLoss();
     64     }
     65 
     66     public static SaveFragment get(FragmentManager fm) {
     67         return (SaveFragment) fm.findFragmentByTag(TAG);
     68     }
     69 
     70     @Override
     71     public View onCreateView(
     72             LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
     73         final Context context = inflater.getContext();
     74 
     75         final View view = inflater.inflate(R.layout.fragment_save, container, false);
     76 
     77         final ImageView icon = (ImageView) view.findViewById(android.R.id.icon);
     78         icon.setImageDrawable(
     79                 IconUtils.loadMimeIcon(context, getArguments().getString(EXTRA_MIME_TYPE)));
     80 
     81         mDisplayName = (EditText) view.findViewById(android.R.id.title);
     82         mDisplayName.addTextChangedListener(mDisplayNameWatcher);
     83         mDisplayName.setText(getArguments().getString(EXTRA_DISPLAY_NAME));
     84         mDisplayName.setOnKeyListener(
     85                 new View.OnKeyListener() {
     86                     @Override
     87                     public boolean onKey(View v, int keyCode, KeyEvent event) {
     88                         // Only handle key-down events. This is simpler, consistent with most other
     89                         // UIs, and enables the handling of repeated key events from holding down a
     90                         // key.
     91                         if (event.getAction() != KeyEvent.ACTION_DOWN) {
     92                             return false;
     93                         }
     94 
     95                         // Returning false in this method will bubble the event up to
     96                         // {@link BaseActivity#onKeyDown}. In order to prevent backspace popping
     97                         // documents once the textView is empty, we are going to trap it here.
     98                         if (keyCode == KeyEvent.KEYCODE_DEL
     99                                 && TextUtils.isEmpty(mDisplayName.getText())) {
    100                             return true;
    101                         }
    102 
    103                         if (keyCode == KeyEvent.KEYCODE_ENTER && mSave.isEnabled()) {
    104                             performSave();
    105                             return true;
    106                         }
    107                         return false;
    108                     }
    109                 });
    110 
    111         mSave = (Button) view.findViewById(android.R.id.button1);
    112         mSave.setOnClickListener(mSaveListener);
    113         mSave.setEnabled(false);
    114 
    115         mProgress = (ProgressBar) view.findViewById(android.R.id.progress);
    116 
    117         return view;
    118     }
    119 
    120     private TextWatcher mDisplayNameWatcher = new TextWatcher() {
    121         @Override
    122         public void onTextChanged(CharSequence s, int start, int before, int count) {
    123             if (mIgnoreNextEdit) {
    124                 mIgnoreNextEdit = false;
    125             } else {
    126                 mReplaceTarget = null;
    127             }
    128         }
    129 
    130         @Override
    131         public void beforeTextChanged(CharSequence s, int start, int count, int after) {
    132             // ignored
    133         }
    134 
    135         @Override
    136         public void afterTextChanged(Editable s) {
    137             // ignored
    138         }
    139     };
    140 
    141     private View.OnClickListener mSaveListener = new View.OnClickListener() {
    142         @Override
    143         public void onClick(View v) {
    144             performSave();
    145         }
    146 
    147     };
    148 
    149     private void performSave() {
    150         final DocumentsActivity activity = DocumentsActivity.get(SaveFragment.this);
    151         if (mReplaceTarget != null) {
    152             activity.onSaveRequested(mReplaceTarget);
    153         } else {
    154             final String mimeType = getArguments().getString(EXTRA_MIME_TYPE);
    155             final String displayName = mDisplayName.getText().toString();
    156             activity.onSaveRequested(mimeType, displayName);
    157         }
    158     }
    159 
    160     /**
    161      * Set given document as target for in-place writing if user hits save
    162      * without changing the filename. Can be set to {@code null} if user
    163      * navigates outside the target directory.
    164      */
    165     public void setReplaceTarget(DocumentInfo replaceTarget) {
    166         mReplaceTarget = replaceTarget;
    167 
    168         if (mReplaceTarget != null) {
    169             getArguments().putString(EXTRA_DISPLAY_NAME, replaceTarget.displayName);
    170             mIgnoreNextEdit = true;
    171             mDisplayName.setText(replaceTarget.displayName);
    172         }
    173     }
    174 
    175     public void prepareForDirectory(DocumentInfo cwd) {
    176         setSaveEnabled(cwd != null && cwd.isCreateSupported());
    177     }
    178 
    179     private void setSaveEnabled(boolean enabled) {
    180         mSave.setEnabled(enabled);
    181     }
    182 
    183     public void setPending(boolean pending) {
    184         mSave.setVisibility(pending ? View.INVISIBLE : View.VISIBLE);
    185         mProgress.setVisibility(pending ? View.VISIBLE : View.GONE);
    186     }
    187 }
    188