/* * Copyright (C) 2012 The CyanogenMod Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.cyanogenmod.filemanager.ui.dialogs; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.text.Editable; import android.text.TextWatcher; import android.view.LayoutInflater; import android.view.View; import android.view.inputmethod.InputMethodManager; import android.widget.EditText; import android.widget.TextView; import com.cyanogenmod.filemanager.R; import com.cyanogenmod.filemanager.model.FileSystemObject; import com.cyanogenmod.filemanager.ui.ThemeManager; import com.cyanogenmod.filemanager.ui.ThemeManager.Theme; import com.cyanogenmod.filemanager.util.DialogHelper; import com.cyanogenmod.filemanager.util.FileHelper; import java.io.File; import java.util.List; /** * A class that wraps a dialog for input a name for file, folder, ... */ public class InputNameDialog implements TextWatcher, DialogInterface.OnCancelListener, DialogInterface.OnDismissListener { private final Context mContext; /** * @hide */ final AlertDialog mDialog; private final TextView mMsg; /** * @hide */ final EditText mEditText; /** * @hide */ final List mFiles; /** * @hide */ final FileSystemObject mFso; private final boolean mAllowFsoName; private DialogInterface.OnCancelListener mOnCancelListener; private DialogInterface.OnDismissListener mOnDismissListener; /** * @hide */ boolean mCancelled; /** * Constructor of InputNameDialog. * * @param context The current context * @param files The files of the current directory (used to validate the name) * @param dialogTitle The dialog title */ public InputNameDialog( final Context context, List files, String dialogTitle) { this(context, files, null, false, dialogTitle); } /** * Constructor of InputNameDialog. * * @param context The current context * @param files The files of the current directory (used to validate the name) * @param fso The original file system object. null if not needed. * @param allowFsoName If allow that the name of the fso will be returned * @param dialogTitle The dialog title */ public InputNameDialog( final Context context, final List files, final FileSystemObject fso, boolean allowFsoName, final String dialogTitle) { super(); //Save the context this.mContext = context; //Save the files this.mFiles = files; this.mFso = fso; this.mAllowFsoName = allowFsoName; this.mCancelled = true; //Create the LayoutInflater li = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); View v = li.inflate(R.layout.input_name_dialog, null); TextView title = (TextView)v.findViewById(R.id.input_name_dialog_label); title.setText(R.string.input_name_dialog_label); this.mEditText = (EditText)v.findViewById(R.id.input_name_dialog_edit); if (this.mFso != null) { this.mEditText.setText(this.mFso.getName()); } else { this.mEditText.setText(dialogTitle); } this.mEditText.selectAll(); this.mEditText.addTextChangedListener(this); this.mMsg = (TextView)v.findViewById(R.id.input_name_dialog_message); // Apply the current theme Theme theme = ThemeManager.getCurrentTheme(context); theme.setBackgroundDrawable(context, v, "background_drawable"); //$NON-NLS-1$ theme.setTextColor(context, title, "text_color"); //$NON-NLS-1$ theme.setTextColor(context, this.mMsg, "text_color"); //$NON-NLS-1$ this.mMsg.setCompoundDrawablesWithIntrinsicBounds( theme.getDrawable(this.mContext, "filesystem_dialog_warning_drawable"), //$NON-NLS-1$ null, null, null); //Create the dialog this.mDialog = DialogHelper.createDialog( context, 0, dialogTitle, v); this.mDialog.setButton( DialogInterface.BUTTON_POSITIVE, context.getString(android.R.string.ok), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { InputNameDialog.this.mCancelled = false; } }); this.mDialog.setOnShowListener(new DialogInterface.OnShowListener() { @Override public void onShow(DialogInterface dialog) { InputMethodManager mgr = (InputMethodManager)context.getSystemService(Context.INPUT_METHOD_SERVICE); mgr.showSoftInput(InputNameDialog.this.mEditText, InputMethodManager.SHOW_IMPLICIT); } }); this.mDialog.setButton( DialogInterface.BUTTON_NEGATIVE, context.getString(android.R.string.cancel), (DialogInterface.OnClickListener)null); this.mDialog.setOnCancelListener(this); this.mDialog.setOnDismissListener(this); // Disable accept button, because name is the same as fso if (this.mFso != null && !this.mAllowFsoName) { this.mEditText.post(new Runnable() { @Override public void run() { InputNameDialog.this.mDialog.getButton( DialogInterface.BUTTON_POSITIVE).setEnabled(false); } }); } else { this.mEditText.post(new Runnable() { @Override public void run() { checkName(InputNameDialog.this.mEditText.getText().toString()); } }); } } /** * Set a listener to be invoked when the dialog is cancelled. *

* This will only be invoked when the dialog is cancelled, if the creator * needs to know when it is dismissed in general, use * {@link #setOnDismissListener}. * * @param onCancelListener The {@link "OnCancelListener"} to use. */ public void setOnCancelListener(DialogInterface.OnCancelListener onCancelListener) { this.mOnCancelListener = onCancelListener; } /** * Set a listener to be invoked when the dialog is dismissed. * * @param onDismissListener The {@link "OnDismissListener"} to use. */ public void setOnDismissListener(DialogInterface.OnDismissListener onDismissListener) { this.mOnDismissListener = onDismissListener; } /** * Method that shows the dialog. */ public void show() { DialogHelper.delegateDialogShow(this.mContext, this.mDialog); } /** * Method that returns the name that the user inputted. * * @return String The name that the user inputted */ public String getName() { return this.mEditText.getText().toString(); } /** * {@inheritDoc} */ @Override public void onTextChanged(CharSequence s, int start, int before, int count) { /**NON BLOCK**/ } /** * {@inheritDoc} */ @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { /**NON BLOCK**/ } /** * {@inheritDoc} */ @Override public void afterTextChanged(Editable s) { String name = s.toString().trim(); checkName(name); } /** * Method that checks the input name * @param name * @hide */ void checkName(String name) { //The name is empty if (name.length() == 0) { setMsg( InputNameDialog.this.mContext.getString( R.string.input_name_dialog_message_empty_name), false); return; } // The path is invalid if (name.indexOf(File.separator) != -1) { setMsg( InputNameDialog.this.mContext.getString( R.string.input_name_dialog_message_invalid_path_name, File.separator), false); return; } // No allow . or .. if (name.compareTo(FileHelper.CURRENT_DIRECTORY) == 0 || name.compareTo(FileHelper.PARENT_DIRECTORY) == 0) { setMsg( InputNameDialog.this.mContext.getString( R.string.input_name_dialog_message_invalid_name), false); return; } // The same name if (this.mFso != null && !this.mAllowFsoName && name.compareTo(this.mFso.getName()) == 0) { setMsg(null, false); return; } // Name exists if (FileHelper.isNameExists(this.mFiles, name)) { setMsg( InputNameDialog.this.mContext.getString( R.string.input_name_dialog_message_name_exists), false); return; } //Valid name setMsg(null, true); } /** * {@inheritDoc} */ @Override public void onDismiss(DialogInterface dialog) { if (!InputNameDialog.this.mCancelled) { if (this.mOnDismissListener != null) { this.mOnDismissListener.onDismiss(dialog); } return; } if (this.mOnCancelListener != null) { this.mOnCancelListener.onCancel(dialog); } } /** * {@inheritDoc} */ @Override public void onCancel(DialogInterface dialog) { if (this.mOnCancelListener != null) { this.mOnCancelListener.onCancel(dialog); } } /** * Method that shows the alert message with the validation warning. * * @param msg The message to show * @param activate If the positive button must be activate */ private void setMsg(String msg, boolean activate) { if (msg == null || msg.length() == 0) { this.mMsg.setVisibility(View.GONE); this.mMsg.setText(""); //$NON-NLS-1$ } else { this.mMsg.setText(msg); this.mMsg.setVisibility(View.VISIBLE); } this.mDialog.getButton(DialogInterface.BUTTON_POSITIVE).setEnabled(activate); } }