├── Ted
├── res
│ ├── drawable-hdpi
│ │ ├── file.png
│ │ ├── up.png
│ │ ├── folder.png
│ │ ├── folder_r.png
│ │ ├── folder_rw.png
│ │ ├── ic_search.png
│ │ ├── file_locked.png
│ │ ├── ic_launcher.png
│ │ ├── file_private.png
│ │ ├── file_unknown.png
│ │ ├── folder_locked.png
│ │ ├── folder_private.png
│ │ ├── ic_menu_recent.png
│ │ ├── ic_menu_save.png
│ │ ├── ic_menu_search.png
│ │ ├── ic_menu_undo.png
│ │ ├── ic_menu_file_new.png
│ │ ├── textfield_sky.9.png
│ │ ├── file_text_favorite.png
│ │ ├── ic_menu_file_open.png
│ │ ├── textfield_black.9.png
│ │ ├── textfield_dracula.9.png
│ │ ├── textfield_matrix.9.png
│ │ ├── textfield_white.9.png
│ │ └── file_text_favorite_readonly.png
│ ├── values
│ │ ├── styles.xml
│ │ ├── dimens.xml
│ │ ├── toasts.xml
│ │ ├── arrays.xml
│ │ ├── history.xml
│ │ └── strings.xml
│ ├── values-es
│ │ ├── styles.xml
│ │ ├── dimens.xml
│ │ ├── history.xml
│ │ ├── toasts.xml
│ │ ├── arrays.xml
│ │ └── strings.xml
│ ├── values-v11
│ │ └── dimens.xml
│ ├── values-fr
│ │ ├── arrays.xml
│ │ ├── toasts.xml
│ │ ├── history.xml
│ │ └── strings.xml
│ ├── drawable
│ │ └── widget_title_background.xml
│ ├── xml
│ │ ├── ted_widget.xml
│ │ └── ted_prefs.xml
│ ├── layout
│ │ ├── dialog_save.xml
│ │ ├── layout_open.xml
│ │ ├── layout_prefs.xml
│ │ ├── layout_widget_config.xml
│ │ ├── layout_save_as.xml
│ │ ├── layout_editor.xml
│ │ ├── widget.xml
│ │ ├── search.xml
│ │ └── layout_about.xml
│ ├── values-sk
│ │ ├── arrays.xml
│ │ ├── toasts.xml
│ │ └── strings.xml
│ └── layout-v11
│ │ └── widget.xml
├── libs
│ └── juniversalchardet-1.0.3.jar
├── .classpath
├── project.properties
├── src
│ └── fr
│ │ └── xgouchet
│ │ └── texteditor
│ │ ├── common
│ │ ├── FontUtils.java
│ │ ├── ComparatorFilesAlpha.java
│ │ ├── TedChangelog.java
│ │ ├── RecentFiles.java
│ │ ├── WidgetPrefs.java
│ │ ├── Settings.java
│ │ ├── TextFileUtils.java
│ │ └── Constants.java
│ │ ├── TedAboutActivity.java
│ │ ├── ui
│ │ ├── adapter
│ │ │ ├── FontListAdapter.java
│ │ │ └── PathListAdapter.java
│ │ └── view
│ │ │ └── AdvancedEditText.java
│ │ ├── undo
│ │ ├── TextChangeDelete.java
│ │ ├── TextChange.java
│ │ ├── TextChangeInsert.java
│ │ └── TextChangeWatcher.java
│ │ ├── TedAppWidgetProvider.java
│ │ ├── TedFontActivity.java
│ │ ├── TedWidgetConfigActivity.java
│ │ ├── TedOpenActivity.java
│ │ ├── TedSaveAsActivity.java
│ │ ├── TedOpenRecentActivity.java
│ │ ├── TedSettingsActivity.java
│ │ └── TedActivity.java
├── .project
├── proguard.cfg
├── changelog.txt
└── AndroidManifest.xml
├── .gitmodules
├── .gitignore
└── README.md
/Ted/res/drawable-hdpi/file.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xgouchet/Ted/HEAD/Ted/res/drawable-hdpi/file.png
--------------------------------------------------------------------------------
/Ted/res/drawable-hdpi/up.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xgouchet/Ted/HEAD/Ted/res/drawable-hdpi/up.png
--------------------------------------------------------------------------------
/Ted/res/drawable-hdpi/folder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xgouchet/Ted/HEAD/Ted/res/drawable-hdpi/folder.png
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "AndroidLib"]
2 | path = AndroidLib
3 | url = git://github.com/xgouchet/AndroidLib.git
4 |
--------------------------------------------------------------------------------
/Ted/res/drawable-hdpi/folder_r.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xgouchet/Ted/HEAD/Ted/res/drawable-hdpi/folder_r.png
--------------------------------------------------------------------------------
/Ted/res/drawable-hdpi/folder_rw.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xgouchet/Ted/HEAD/Ted/res/drawable-hdpi/folder_rw.png
--------------------------------------------------------------------------------
/Ted/res/drawable-hdpi/ic_search.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xgouchet/Ted/HEAD/Ted/res/drawable-hdpi/ic_search.png
--------------------------------------------------------------------------------
/Ted/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Ted/libs/juniversalchardet-1.0.3.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xgouchet/Ted/HEAD/Ted/libs/juniversalchardet-1.0.3.jar
--------------------------------------------------------------------------------
/Ted/res/drawable-hdpi/file_locked.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xgouchet/Ted/HEAD/Ted/res/drawable-hdpi/file_locked.png
--------------------------------------------------------------------------------
/Ted/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xgouchet/Ted/HEAD/Ted/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/Ted/res/values-es/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Ted/res/drawable-hdpi/file_private.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xgouchet/Ted/HEAD/Ted/res/drawable-hdpi/file_private.png
--------------------------------------------------------------------------------
/Ted/res/drawable-hdpi/file_unknown.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xgouchet/Ted/HEAD/Ted/res/drawable-hdpi/file_unknown.png
--------------------------------------------------------------------------------
/Ted/res/drawable-hdpi/folder_locked.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xgouchet/Ted/HEAD/Ted/res/drawable-hdpi/folder_locked.png
--------------------------------------------------------------------------------
/Ted/res/drawable-hdpi/folder_private.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xgouchet/Ted/HEAD/Ted/res/drawable-hdpi/folder_private.png
--------------------------------------------------------------------------------
/Ted/res/drawable-hdpi/ic_menu_recent.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xgouchet/Ted/HEAD/Ted/res/drawable-hdpi/ic_menu_recent.png
--------------------------------------------------------------------------------
/Ted/res/drawable-hdpi/ic_menu_save.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xgouchet/Ted/HEAD/Ted/res/drawable-hdpi/ic_menu_save.png
--------------------------------------------------------------------------------
/Ted/res/drawable-hdpi/ic_menu_search.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xgouchet/Ted/HEAD/Ted/res/drawable-hdpi/ic_menu_search.png
--------------------------------------------------------------------------------
/Ted/res/drawable-hdpi/ic_menu_undo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xgouchet/Ted/HEAD/Ted/res/drawable-hdpi/ic_menu_undo.png
--------------------------------------------------------------------------------
/Ted/res/drawable-hdpi/ic_menu_file_new.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xgouchet/Ted/HEAD/Ted/res/drawable-hdpi/ic_menu_file_new.png
--------------------------------------------------------------------------------
/Ted/res/drawable-hdpi/textfield_sky.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xgouchet/Ted/HEAD/Ted/res/drawable-hdpi/textfield_sky.9.png
--------------------------------------------------------------------------------
/Ted/res/drawable-hdpi/file_text_favorite.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xgouchet/Ted/HEAD/Ted/res/drawable-hdpi/file_text_favorite.png
--------------------------------------------------------------------------------
/Ted/res/drawable-hdpi/ic_menu_file_open.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xgouchet/Ted/HEAD/Ted/res/drawable-hdpi/ic_menu_file_open.png
--------------------------------------------------------------------------------
/Ted/res/drawable-hdpi/textfield_black.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xgouchet/Ted/HEAD/Ted/res/drawable-hdpi/textfield_black.9.png
--------------------------------------------------------------------------------
/Ted/res/drawable-hdpi/textfield_dracula.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xgouchet/Ted/HEAD/Ted/res/drawable-hdpi/textfield_dracula.9.png
--------------------------------------------------------------------------------
/Ted/res/drawable-hdpi/textfield_matrix.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xgouchet/Ted/HEAD/Ted/res/drawable-hdpi/textfield_matrix.9.png
--------------------------------------------------------------------------------
/Ted/res/drawable-hdpi/textfield_white.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xgouchet/Ted/HEAD/Ted/res/drawable-hdpi/textfield_white.9.png
--------------------------------------------------------------------------------
/Ted/res/drawable-hdpi/file_text_favorite_readonly.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xgouchet/Ted/HEAD/Ted/res/drawable-hdpi/file_text_favorite_readonly.png
--------------------------------------------------------------------------------
/Ted/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 4dp
5 | 72dp
6 |
7 |
--------------------------------------------------------------------------------
/Ted/res/values-es/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 4dp
5 | 72dp
6 |
7 |
--------------------------------------------------------------------------------
/Ted/res/values-v11/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 4dp
5 | 40dp
6 |
7 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # built application files
2 | *.apk
3 | *.ap_
4 |
5 | # files for the dex VM
6 | *.dex
7 |
8 | # Java class files
9 | *.class
10 |
11 | # generated files
12 | bin/
13 | gen/
14 |
15 | # Local configuration file (sdk path, etc)
16 | local.properties
17 | .gitattributes
18 |
19 | # Eclipse project files
20 | #.classpath
21 | #.project
22 | .metadata
23 |
--------------------------------------------------------------------------------
/Ted/res/values-fr/arrays.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | - Classique
7 | - Negatif
8 | - Matrix
9 | - Ciel Bleu
10 | - Dracula
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/Ted/res/drawable/widget_title_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/Ted/res/xml/ted_widget.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
--------------------------------------------------------------------------------
/Ted/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/Ted/project.properties:
--------------------------------------------------------------------------------
1 | # This file is automatically generated by Android Tools.
2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3 | #
4 | # This file must be checked in Version Control Systems.
5 | #
6 | # To customize properties used by the Ant build system use,
7 | # "ant.properties", and override values to adapt the script to your
8 | # project structure.
9 |
10 | # Project target.
11 | target=android-17
12 | android.library.reference.1=../AndroidLib
13 |
--------------------------------------------------------------------------------
/Ted/src/fr/xgouchet/texteditor/common/FontUtils.java:
--------------------------------------------------------------------------------
1 | package fr.xgouchet.texteditor.common;
2 |
3 | import java.io.File;
4 |
5 | import android.content.Context;
6 |
7 | public class FontUtils {
8 |
9 | /**
10 | * @param ctx
11 | * the current application context
12 | * @return the app folder for fonts
13 | */
14 | public static File getAppFontFolder(Context ctx) {
15 | return ctx.getDir(Constants.FONT_FOLDER_NAME, Context.MODE_PRIVATE);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Ted/src/fr/xgouchet/texteditor/TedAboutActivity.java:
--------------------------------------------------------------------------------
1 | package fr.xgouchet.texteditor;
2 |
3 | import android.os.Bundle;
4 | import fr.xgouchet.androidlib.ui.activity.AboutActivity;
5 |
6 | public class TedAboutActivity extends AboutActivity {
7 |
8 | /**
9 | * @see android.app.Activity#onCreate(android.os.Bundle)
10 | */
11 | protected void onCreate(Bundle savedInstanceState) {
12 | super.onCreate(savedInstanceState);
13 |
14 | setContentView(R.layout.layout_about);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Ted/res/layout/dialog_save.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/Ted/res/layout/layout_open.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
12 |
13 |
14 |
20 |
21 |
--------------------------------------------------------------------------------
/Ted/src/fr/xgouchet/texteditor/common/ComparatorFilesAlpha.java:
--------------------------------------------------------------------------------
1 | package fr.xgouchet.texteditor.common;
2 |
3 | import java.io.File;
4 | import java.util.Comparator;
5 |
6 | /**
7 | * Compare files Alphabetically (w/ folders listed first)
8 | *
9 | * @author x.gouchet
10 | *
11 | */
12 | public class ComparatorFilesAlpha implements Comparator {
13 |
14 | /**
15 | * @see Comparator#compare(Object, Object)
16 | */
17 | public int compare(File file1, File file2) {
18 | // sort folders first
19 | if ((file1.isDirectory()) && (!file2.isDirectory()))
20 | return -1;
21 | if ((!file1.isDirectory()) && (file2.isDirectory()))
22 | return 1;
23 |
24 | // here both are folders or both are files : sort alpha
25 | return file1.getName().toLowerCase().compareTo(
26 | file2.getName().toLowerCase());
27 | }
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/Ted/src/fr/xgouchet/texteditor/common/TedChangelog.java:
--------------------------------------------------------------------------------
1 | package fr.xgouchet.texteditor.common;
2 |
3 | import fr.xgouchet.androidlib.common.AbstractChangeLog;
4 | import fr.xgouchet.texteditor.R;
5 |
6 | public class TedChangelog extends AbstractChangeLog {
7 |
8 | /**
9 | * @see fr.xgouchet.androidlib.common.ChangeLog#getTitleResourceForVersion(int)
10 | */
11 | public int getTitleResourceForVersion(int version) {
12 | int res = 0;
13 | switch (version) {
14 | case 18:
15 | default:
16 | res = R.string.release18;
17 | }
18 | return res;
19 | }
20 |
21 | /**
22 | * @see fr.xgouchet.androidlib.common.ChangeLog#getChangeLogResourceForVersion(int)
23 | */
24 | public int getChangeLogResourceForVersion(int version) {
25 | int res = 0;
26 | switch (version) {
27 | case 18:
28 | default:
29 | res = R.string.release18_log;
30 | }
31 | return res;
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/Ted/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | Ted
4 |
5 |
6 |
7 |
8 |
9 | com.android.ide.eclipse.adt.ResourceManagerBuilder
10 |
11 |
12 |
13 |
14 | com.android.ide.eclipse.adt.PreCompilerBuilder
15 |
16 |
17 |
18 |
19 | org.eclipse.jdt.core.javabuilder
20 |
21 |
22 |
23 |
24 | com.android.ide.eclipse.adt.ApkBuilder
25 |
26 |
27 |
28 |
29 |
30 | com.android.ide.eclipse.adt.AndroidNature
31 | org.eclipse.jdt.core.javanature
32 |
33 |
34 |
--------------------------------------------------------------------------------
/Ted/res/layout/layout_prefs.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
18 |
19 |
23 |
24 |
--------------------------------------------------------------------------------
/Ted/res/layout/layout_widget_config.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
15 |
16 |
21 |
22 |
23 |
30 |
31 |
--------------------------------------------------------------------------------
/Ted/res/values-sk/arrays.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | - Klasická
6 | - Negatív
7 | - Matrix
8 | - Obloha
9 | - Drakula
10 |
11 |
12 |
13 | - 6 bodov
14 | - 8 bodov
15 | - 10 bodov
16 | - 12 bodov
17 | - 14 bodov
18 | - 16 bodov
19 | - 18 bodov
20 | - 24 bodov
21 | - 32 bodov
22 | - 48 bodov
23 |
24 |
25 |
26 | - Android/Linux/Unix
27 | - Windows/Symbian/Palm
28 | - Mac/iPhone
29 |
30 |
31 |
32 | - ASCII
33 | - Latin 1
34 | - UTF 8
35 |
36 |
37 |
--------------------------------------------------------------------------------
/Ted/res/layout/layout_save_as.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
12 |
13 |
21 |
22 |
23 |
24 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/Ted/res/layout/layout_editor.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
20 |
21 |
22 |
23 |
24 |
30 |
31 |
--------------------------------------------------------------------------------
/Ted/res/layout-v11/widget.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
16 |
17 |
32 |
33 |
--------------------------------------------------------------------------------
/Ted/proguard.cfg:
--------------------------------------------------------------------------------
1 | -optimizationpasses 5
2 | -dontusemixedcaseclassnames
3 | -dontskipnonpubliclibraryclasses
4 | -dontpreverify
5 | -verbose
6 | -optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
7 |
8 | -keep public class * extends android.app.Activity
9 | -keep public class * extends android.app.Application
10 | -keep public class * extends android.app.Service
11 | -keep public class * extends android.content.BroadcastReceiver
12 | -keep public class * extends android.content.ContentProvider
13 | -keep public class * extends android.app.backup.BackupAgentHelper
14 | -keep public class * extends android.preference.Preference
15 | -keep public class com.android.vending.licensing.ILicensingService
16 |
17 | -keepclasseswithmembernames class * {
18 | native ;
19 | }
20 |
21 | -keepclasseswithmembers class * {
22 | public (android.content.Context, android.util.AttributeSet);
23 | }
24 |
25 | -keepclasseswithmembers class * {
26 | public (android.content.Context, android.util.AttributeSet, int);
27 | }
28 |
29 | -keepclassmembers class * extends android.app.Activity {
30 | public void *(android.view.View);
31 | }
32 |
33 | -keepclassmembers enum * {
34 | public static **[] values();
35 | public static ** valueOf(java.lang.String);
36 | }
37 |
38 | -keep class * implements android.os.Parcelable {
39 | public static final android.os.Parcelable$Creator *;
40 | }
41 |
--------------------------------------------------------------------------------
/Ted/res/layout/widget.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
17 |
18 |
34 |
35 |
--------------------------------------------------------------------------------
/Ted/res/layout/search.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
14 |
15 |
24 |
25 |
31 |
32 |
38 |
39 |
--------------------------------------------------------------------------------
/Ted/src/fr/xgouchet/texteditor/ui/adapter/FontListAdapter.java:
--------------------------------------------------------------------------------
1 | package fr.xgouchet.texteditor.ui.adapter;
2 |
3 | import java.io.File;
4 | import java.util.List;
5 |
6 | import android.content.Context;
7 | import android.graphics.Typeface;
8 | import android.util.Log;
9 | import android.view.View;
10 | import android.view.ViewGroup;
11 | import android.widget.TextView;
12 | import fr.xgouchet.androidlib.R;
13 | import fr.xgouchet.androidlib.data.FileUtils;
14 | import fr.xgouchet.androidlib.ui.adapter.FileListAdapter;
15 |
16 | public class FontListAdapter extends FileListAdapter {
17 |
18 | /**
19 | * Constructor
20 | *
21 | * @param context
22 | * The current context
23 | * @param objects
24 | * The objects to represent in the ListView.
25 | * @param folder
26 | * the parent folder of the items presented, or null if the top
27 | * folder should not be displayed as up
28 | */
29 | public FontListAdapter(Context context, List objects) {
30 | super(context, objects, null);
31 | }
32 |
33 | /**
34 | * @see fr.xgouchet.androidlib.ui.adapter.FileListAdapter#getView(int,
35 | * android.view.View, android.view.ViewGroup)
36 | */
37 | public View getView(int position, View convertView, ViewGroup parent) {
38 | View v = super.getView(position, convertView, parent);
39 |
40 | File f = getItem(position);
41 |
42 | if (FileUtils.getFileExtension(f).equalsIgnoreCase("ttf")) {
43 | TextView t = (TextView) v.findViewById(R.id.textFileName);
44 | Typeface font = Typeface.DEFAULT;
45 | try {
46 | font = Typeface.createFromFile(f);
47 | t.setTypeface(font);
48 | } catch (RuntimeException e) {
49 | Log.w("TED", "Unable to create a font from " + f.getName());
50 | }
51 | }
52 |
53 | return v;
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | # ABOUT
3 |
4 | Ted is an Open Source, Ad-free, lightweight text editor for Android, meant as a Notepad application, and not meant to edit big files.
5 | You can create new text file, open existing files and of course save them. You can also display line numbers and open recent files. You can also search for text inside the opened file.
6 |
7 | The official Ted app is available on the [Google Play Store](https://play.google.com/store/apps/details?id=fr.xgouchet.texteditor).
8 |
9 | ## Icons
10 |
11 | All the icons and graphics used in Ted are licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
12 |
13 |
14 | # LICENCE
15 |
16 | Copyright (C) 2012 by Xavier GOUCHET (http://xgouchet.fr, android@xgouchet.fr)
17 | MIT Licence / Expat
18 |
19 | Permission is hereby granted, free of charge, to any person obtaining a copy
20 | of this software and associated documentation files (the "Software"), to deal
21 | in the Software without restriction, including without limitation the rights
22 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
23 | copies of the Software, and to permit persons to whom the Software is
24 | furnished to do so, subject to the following conditions:
25 |
26 | The above copyright notice and this permission notice shall be included in
27 | all copies or substantial portions of the Software.
28 |
29 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
30 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
31 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
32 | AUTHORS ( XAVIER GOUCHET ) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
33 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
34 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
35 | THE SOFTWARE.
36 |
--------------------------------------------------------------------------------
/Ted/src/fr/xgouchet/texteditor/ui/adapter/PathListAdapter.java:
--------------------------------------------------------------------------------
1 | package fr.xgouchet.texteditor.ui.adapter;
2 |
3 | import java.util.ArrayList;
4 |
5 | import android.content.Context;
6 | import android.view.LayoutInflater;
7 | import android.view.View;
8 | import android.view.ViewGroup;
9 | import android.widget.ArrayAdapter;
10 | import android.widget.TextView;
11 | import fr.xgouchet.texteditor.R;
12 |
13 | /**
14 | * A File List Adapter
15 | *
16 | * @author x.gouchet
17 | *
18 | */
19 | public class PathListAdapter extends ArrayAdapter {
20 |
21 | /**
22 | * Constructor
23 | *
24 | * @param context
25 | * The current context
26 | * @param objects
27 | * The objects to represent in the ListView.
28 | */
29 | public PathListAdapter(Context context, ArrayList objects) {
30 | super(context, R.layout.item_file, objects);
31 | }
32 |
33 | /**
34 | * @see ArrayAdapter#getView(int, View, ViewGroup)
35 | */
36 | public View getView(int position, View convertView, ViewGroup parent) {
37 | View v;
38 | String path;
39 | TextView compound;
40 |
41 | // recycle view
42 | v = convertView;
43 | if (v == null) {
44 | LayoutInflater vi = (LayoutInflater) getContext().getSystemService(
45 | Context.LAYOUT_INFLATER_SERVICE);
46 | v = vi.inflate(R.layout.item_file, null);
47 | }
48 |
49 | // get displayed file and current view
50 | path = getItem(position);
51 |
52 | // set the layout content
53 | compound = (TextView) v.findViewById(R.id.textFileName);
54 | if (compound != null) {
55 | if (path == null) {
56 | compound.setText("");
57 | compound.setCompoundDrawablesWithIntrinsicBounds(
58 | R.drawable.file_unknown, 0, 0, 0);
59 | } else {
60 | compound.setText(path);
61 | compound.setCompoundDrawablesWithIntrinsicBounds(
62 | R.drawable.file, 0, 0, 0);
63 | }
64 | }
65 | return v;
66 | }
67 |
68 | }
69 |
--------------------------------------------------------------------------------
/Ted/res/values-es/history.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 1.8 (10 nov 2012)
7 | "- Corrección de bug : archivo actual / último archivo abierto
8 | - Sistema de notificaciones actualizado
9 | - Ahora es posible modificar la fuente empleada por el editor (posibilidad de cargar cualquier fuente TTF desde el almacenamiento externo)"
10 |
11 |
12 | 1.7 (16 julio 2012)
13 | "- Correción de bug : Cuelgue al guardar en algunos teléfonos
14 | - Ahora es posible desactivar el autoguardado en los archivos ya existentes"
15 |
16 |
17 | 1.6 (9 julio 2012)
18 | "- Añadido guardado automático
19 | - Arreglado un bug con la búsqueda de archivos "
20 |
21 |
22 | 1.5 (21 junio 2012)
23 | "- Adaptación para Ice Cream Sandwich
24 | - Mejora en la característica de deshacer
25 | - Añadido Widget
26 | - Añadida opción de abrir un archivo al inicio
27 | - Nuevos gráficos (hechos por mí ^^)"
28 |
29 |
30 | 1.3 (5 mayo 2012)
31 | "- Implementada opción de deshacer
32 | - Añadidas optimizaciones de rendimiento"
33 |
34 |
35 | 1.2 (18 abr. 2012)
36 | "- Arreglado un bug en el scroll"
37 |
38 |
39 | 1.1 (10 abr. 2012)
40 | "- Arreglados los cuelgues al inicio
41 | - Añadido scroll por deslizamiento (fling)
42 | - Muestra la línea activa
43 | - Añadido un tema nuevo (si necesitas más, pídelos)
44 | 1.0 (27 feb. 2012)
45 | "- Nueva versión remozada
46 | - Soporte de diversas codificaciones (incluye UTF-8)
47 | - Previene pérdida de datos al guardar archivos muy grande (ojo! Ted no está pensado para abrir grandes archivos!)
48 | - Añadido un tema nuevo (si necesitas más, pídelos)
49 | - El autoguardado ahora pide confirmación (previene el guardado de cambios no deseados)"
50 |
51 |
--------------------------------------------------------------------------------
/Ted/src/fr/xgouchet/texteditor/undo/TextChangeDelete.java:
--------------------------------------------------------------------------------
1 | package fr.xgouchet.texteditor.undo;
2 |
3 | import fr.xgouchet.texteditor.BuildConfig;
4 | import android.text.Editable;
5 | import android.util.Log;
6 |
7 | public class TextChangeDelete implements TextChange {
8 |
9 | protected StringBuffer mSequence;
10 | protected int mStart;
11 |
12 | /**
13 | * @param seq
14 | * the sequence being deleted
15 | * @param start
16 | * the start index
17 | */
18 | public TextChangeDelete(CharSequence seq, int start) {
19 | mSequence = new StringBuffer();
20 | mSequence.append(seq);
21 | mStart = start;
22 | }
23 |
24 | /**
25 | * @see fr.xgouchet.texteditor.undo.TextChange#undo(android.text.Editable)
26 | */
27 | public int undo(Editable s) {
28 | s.insert(mStart, mSequence);
29 | return mStart + mSequence.length();
30 | }
31 |
32 | /**
33 | * @see fr.xgouchet.texteditor.undo.TextChange#getCaret()
34 | */
35 | public int getCaret() {
36 | if (mSequence.toString().contains(" "))
37 | return -1;
38 | if (mSequence.toString().contains("\n"))
39 | return -1;
40 | return mStart;
41 | }
42 |
43 | /**
44 | * @see fr.xgouchet.texteditor.undo.TextChange#append(java.lang.CharSequence)
45 | */
46 | public void append(CharSequence seq) {
47 | mSequence.insert(0, seq);
48 | if (BuildConfig.DEBUG)
49 | Log.d(TAG, mSequence.toString());
50 | mStart -= seq.length();
51 | }
52 |
53 | /**
54 | * @see fr.xgouchet.texteditor.undo.TextChange#canMergeChangeAfter(java.lang.CharSequence,
55 | * int, int, int)
56 | */
57 | public boolean canMergeChangeBefore(CharSequence s, int start, int count, int after) {
58 | CharSequence sub;
59 | if (mSequence.toString().contains(" "))
60 | return false;
61 | if (mSequence.toString().contains("\n"))
62 | return false;
63 | if ((count != 1) || (start + count != mStart))
64 | return false;
65 |
66 | sub = s.subSequence(start, start + count);
67 | append(sub);
68 | return true;
69 | }
70 |
71 | /**
72 | * @see fr.xgouchet.texteditor.undo.TextChange#canMergeChangeBefore(java.lang.CharSequence,
73 | * int, int, int)
74 | */
75 | public boolean canMergeChangeAfter(CharSequence s, int start, int before, int count) {
76 | return false;
77 | }
78 |
79 | /**
80 | * @see java.lang.Object#toString()
81 | */
82 | public String toString() {
83 | return "-\"" + mSequence.toString().replaceAll("\n", "~") + "\" @" + mStart;
84 | }
85 |
86 | }
87 |
--------------------------------------------------------------------------------
/Ted/src/fr/xgouchet/texteditor/undo/TextChange.java:
--------------------------------------------------------------------------------
1 | package fr.xgouchet.texteditor.undo;
2 |
3 | import android.text.Editable;
4 | import fr.xgouchet.texteditor.common.Constants;
5 |
6 | public interface TextChange extends Constants {
7 |
8 | /**
9 | * Undo this change
10 | *
11 | * @param text
12 | * the editable object on which the undo is done
13 | * @return the caret position after the undo
14 | */
15 | public int undo(Editable text);
16 |
17 | /**
18 | * Method is deprecated, you should use the canMergeXXX methods instead
19 | *
20 | * @return the caret position after this change
21 | */
22 | @Deprecated
23 | public int getCaret();
24 |
25 | /**
26 | * Method is deprecated, you should use the canMergeXXX methods instead
27 | *
28 | * @param sequence
29 | * the sequence being appended to this {@link TextChange}
30 | */
31 | @Deprecated
32 | public void append(CharSequence sequence);
33 |
34 | /**
35 | * A change to the text {@linkplain s} will be made, where the
36 | * {@linkplain count} characters starting at {@linkplain start} will be
37 | * replaced by {@linkplain after} characters
38 | *
39 | * If possible, this change is merged in this {@link TextChange}
40 | *
41 | * @param s
42 | * the sequence being changed
43 | * @param start
44 | * the start index
45 | * @param count
46 | * the number of characters that will change
47 | * @param after
48 | * the number of characters that will replace the old ones
49 | * @return if the change can be merged with this {@link TextChange}
50 | */
51 | public boolean canMergeChangeBefore(CharSequence s, int start, int count,
52 | int after);
53 |
54 | /**
55 | * A change to the text {@linkplain s} has been made, where the
56 | * {@linkplain count} characters starting at {@linkplain start} have
57 | * replaced the substring of length {@linkplain before}
58 | *
59 | * If possible, this change is merged in this {@link TextChange}
60 | *
61 | * @param s
62 | * the sequence being changed
63 | * @param start
64 | * the start index
65 | * @param before
66 | * the number of character that were replaced
67 | * @param count
68 | * the number of characters that will change
69 | * @return if the change can be merged with this {@link TextChange}
70 | */
71 | public boolean canMergeChangeAfter(CharSequence s, int start, int before,
72 | int count);
73 |
74 | }
75 |
--------------------------------------------------------------------------------
/Ted/changelog.txt:
--------------------------------------------------------------------------------
1 |
2 |
3 | RELEASE 1.5 (30 june 2012)
4 | - New Graphics
5 | - Undo bugs with ICS
6 | - New file extensions added (.ini, .rc, .sh, .log, .db, .conf, .cfg, .bat)
7 | - Better integration with ICS
8 |
9 |
10 | RELEASE 1.3 (5 may 2012)
11 | - Added an undo option (check the settings)
12 | - Added some performance tweaks
13 |
14 | RELEASE 1.2 (18 apr. 2012)
15 | - Fixed the scroll bug since last update
16 | - fixed the fling options in the settings (option was always active)
17 |
18 | RELEASE 1.1 (10 apr. 2012)
19 | - Fixed the crash at start caused by the last update
20 | - Added Fling to Scroll (launches the scroll to navigate in large files)
21 | - Display the active line
22 | - Added new color theme (ask for more if needed)
23 |
24 | RELEASE 1.0 (27 feb. 2012)
25 | - Brand new release version
26 | - Supports multiple encoding (including UTF-8)
27 | - Prevent data loss when saving really big files (note that Ted is not meant to open big files though)
28 | - Added new color theme (ask for more if needed)
29 | - Replaced the autosave with a warning and popup (prevent saving unwanted changes)
30 |
31 | -----------------------------------------------------------------------
32 | βetα 0.9 (7 janv. 2010)
33 | - Bug fixed : severall crash on start
34 | - Added a search tool
35 | - Ted is listed when opening html, rss, css, php and xml files from any file browser (ask for other types if needed)
36 |
37 | βetα 0.8 (23 dec. 2010)
38 | - Automatic save can be disabled in the settings
39 |
40 | βetα 0.7 (19 dec. 2010)
41 | - App can be installed on the SD Card (on Android 2.2)
42 | - Automatic detection of end of line in opened files, possibility to define a default end of line for new files
43 | - Bigger dialog boxes
44 | - Bug fixed when openning big files
45 |
46 | βetα 0.6 (8 dec. 2010)
47 | - Possibility to change text size in the settings.
48 | - Possibility to open read-only text files from other location than the SD card
49 | - Added a backup function for unsaved text
50 |
51 | βetα 0.5 (29 nov. 2010)
52 | - Bug fixed while opening some files
53 | - New Graphics
54 |
55 | βetα 0.4 (27 nov. 2010)
56 | - Remembers the files opened recently (number of recent files can be changed)
57 | - display lines numbers (can be changed in the settings)
58 | - automatically break lines to keep a width of one page (can be changed in the settings)
59 |
60 | βetα 0.3 (25 nov. 2010)
61 | - Bug fixed : crash when trying to open online files
62 |
63 | βetα 0.2 (13 nov. 2010)
64 | - Open existing files
65 | - Save and save as
--------------------------------------------------------------------------------
/Ted/src/fr/xgouchet/texteditor/common/RecentFiles.java:
--------------------------------------------------------------------------------
1 | package fr.xgouchet.texteditor.common;
2 |
3 | import java.io.File;
4 | import java.util.ArrayList;
5 |
6 | import fr.xgouchet.texteditor.BuildConfig;
7 |
8 | import android.content.SharedPreferences;
9 | import android.content.SharedPreferences.Editor;
10 | import android.util.Log;
11 |
12 | /**
13 | * Storage for a recent files list
14 | *
15 | * TODO code review
16 | */
17 | public class RecentFiles implements Constants {
18 |
19 | /**
20 | * loads the recent files from shared preferences
21 | *
22 | * @param saved
23 | * the previously saved string
24 | */
25 | public static void loadRecentFiles(String saved) {
26 | PATHS = new ArrayList();
27 | String[] paths = saved.split(File.pathSeparator);
28 | for (String path : paths) {
29 | if (path.length() > 0) {
30 | PATHS.add(path);
31 | }
32 | if (PATHS.size() == Settings.MAX_RECENT_FILES) {
33 | break;
34 | }
35 | }
36 | }
37 |
38 | /**
39 | * Saves the preferences when they have been edited
40 | *
41 | * @param prefs
42 | * the preferences to save to
43 | */
44 | public static void saveRecentList(SharedPreferences prefs) {
45 | String str = "";
46 | Editor editor;
47 |
48 | for (String path : PATHS) {
49 | str += path;
50 | str += File.pathSeparator;
51 | }
52 |
53 | editor = prefs.edit();
54 | editor.putString(PREFERENCE_RECENTS, str);
55 | editor.commit();
56 | }
57 |
58 | /**
59 | * @return the list of most recent files
60 | */
61 | public static ArrayList getRecentFiles() {
62 | return PATHS;
63 | }
64 |
65 | /**
66 | * Updates the recent list with a path. If the path is already in the list,
67 | * bring it back to top, else add it.
68 | *
69 | * @param path
70 | * the path to insert
71 | */
72 | public static void updateRecentList(String path) {
73 | if (PATHS.contains(path)) {
74 | PATHS.remove(path);
75 | }
76 |
77 | PATHS.add(0, path);
78 | while (PATHS.size() > Settings.MAX_RECENT_FILES) {
79 | PATHS.remove(Settings.MAX_RECENT_FILES);
80 | }
81 | if (BuildConfig.DEBUG) {
82 | Log.d(TAG, "added path to recent files : " + path);
83 | }
84 | }
85 |
86 | /**
87 | * Removes a path from the recent files list
88 | *
89 | * @param path
90 | * the path to remove
91 | */
92 | public static void removePath(String path) {
93 | if (PATHS.contains(path)) {
94 | PATHS.remove(path);
95 | }
96 | }
97 |
98 | /** the list of paths in the recent list */
99 | private static ArrayList PATHS;
100 | }
101 |
--------------------------------------------------------------------------------
/Ted/src/fr/xgouchet/texteditor/TedAppWidgetProvider.java:
--------------------------------------------------------------------------------
1 | package fr.xgouchet.texteditor;
2 |
3 | import java.io.File;
4 |
5 | import android.app.PendingIntent;
6 | import android.appwidget.AppWidgetManager;
7 | import android.appwidget.AppWidgetProvider;
8 | import android.content.ComponentName;
9 | import android.content.Context;
10 | import android.content.Intent;
11 | import android.net.Uri;
12 | import android.util.Log;
13 | import android.widget.RemoteViews;
14 | import fr.xgouchet.texteditor.common.Constants;
15 | import fr.xgouchet.texteditor.common.WidgetPrefs;
16 |
17 | public class TedAppWidgetProvider extends AppWidgetProvider implements Constants {
18 |
19 | /**
20 | * @see android.appwidget.AppWidgetProvider#onUpdate(android.content.Context,
21 | * android.appwidget.AppWidgetManager, int[])
22 | */
23 | public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
24 |
25 | AppWidgetManager manager;
26 | ComponentName widgetName;
27 |
28 | if (BuildConfig.DEBUG)
29 | Log.i(TAG, "onUpdate widgets");
30 |
31 | manager = AppWidgetManager.getInstance(context);
32 | widgetName = new ComponentName(context, TedAppWidgetProvider.class);
33 | int[] widgetIds = manager.getAppWidgetIds(widgetName);
34 |
35 | for (int widgetId : widgetIds) {
36 | updateWidget(context, manager, widgetId);
37 | }
38 | }
39 |
40 | /**
41 | * @see android.appwidget.AppWidgetProvider#onDeleted(android.content.Context,
42 | * int[])
43 | */
44 | public void onDeleted(Context context, int[] appWidgetIds) {
45 |
46 | for (int widgetId : appWidgetIds) {
47 | WidgetPrefs.delete(context, widgetId);
48 | }
49 | }
50 |
51 | public static void updateWidget(Context context, AppWidgetManager manager, int widgetId) {
52 | Intent intent;
53 | PendingIntent pendingIntent;
54 | RemoteViews views;
55 | WidgetPrefs pref;
56 | File targetFile;
57 |
58 | pref = new WidgetPrefs();
59 | pref.load(context, widgetId);
60 |
61 | if (BuildConfig.DEBUG)
62 | Log.i(TAG, "Updating widgetId " + String.valueOf(widgetId));
63 |
64 | targetFile = new File(pref.mTargetPath);
65 |
66 | intent = new Intent(context, TedActivity.class);
67 | intent.setAction(ACTION_WIDGET_OPEN);
68 | intent.setData(Uri.fromFile(targetFile));
69 | intent.putExtra(EXTRA_FORCE_READ_ONLY, pref.mReadOnly);
70 |
71 | pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
72 |
73 | views = new RemoteViews(context.getPackageName(), R.layout.widget);
74 |
75 | views.setOnClickPendingIntent(R.id.widgetLayout, pendingIntent);
76 | if (pref.mReadOnly)
77 | views.setImageViewResource(R.id.icon, R.drawable.file_text_favorite_readonly);
78 | else
79 | views.setImageViewResource(R.id.icon, R.drawable.file_text_favorite);
80 | views.setTextViewText(R.id.textFileName, targetFile.getName());
81 |
82 | manager.updateAppWidget(widgetId, views);
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/Ted/res/values/toasts.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | There are no recent files to load
5 | "File doesn't exist anymore, removing from recent list."
6 | File deleted from recent list
7 | Unable to open the file, URI is invalid
8 | Unable to open the file
9 | Unable to load the file browser
10 | Unable to open the recent files list
11 | Unable to load the file browser
12 | Unable to load the settings page
13 | Unable to load the about page
14 | Unable to open the file, not enough memory
15 | Unable to open the file (maybe the file is too big, or corrupted)
16 | Unable to save, path is null
17 | Unable to save to temp file
18 | Unable to save (error while copying temp file to save location)
19 | Unable to save (error while copying temp file to save location)
20 | File saved
21 | "Can't use this folder cause it isn't writeable"
22 | "Can't use this file cause it isn't readable"
23 | No match was found in the current file
24 | No more match found in the current file
25 | Type a text to search in the search bar
26 | The filename must not be empty
27 | Nothing to undo anymore.
28 | Nothing to undo anymore. Press Back one more time to quit.
29 | Default file not found, try setting a new one in the settings.
30 | "Can't open default file cause it isn't readable"
31 | Select a file to associate with this new widget
32 | Select a file to open
33 | Select a file to open when you launch Ted from your home screen
34 | "The opened file was saved automatically, and will be opened at next startup"
35 |
36 |
--------------------------------------------------------------------------------
/Ted/res/values-es/toasts.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | No hay archivos recientes
5 | "Ya no existe el archivo. Se elimina de la lista de recientes."
6 | Elemento eliminado de la lista de recientes
7 | Error al abrir el archivo, dirección no válida
8 | Error al abrir el archivo
9 | Error al cargar el explorador de archivos
10 | Error al cargar la lista de archivos recientes
11 | Error al cargar el explorador de archivos
12 | Error al cargar la pantalla de configuración
13 | Error al cargar "Acerca de"
14 | Error al abrir el archivo. Memoria insuficiente
15 | Error al abrir el archivo (Archivo demasiado grande o corrupto)
16 | Error al guardar. Escribe un destino
17 | Error al guardar el archivo temporal
18 | Error al guardar (fallo al escribir el archivo en su ubicación definitiva)
19 | Error al guardar (fallo al escribir el archivo en su ubicación definitiva)
20 | Archivo guardado
21 | "No se puede escribir en el directorio. Permiso denegado"
22 | "No se puede leer el directorio. Permiso denegado"
23 | No se encuentran coincidencias
24 | No se encuentran más coincidencias
25 | Escribe algo en la barra de búsqueda
26 | Escribe un nombre de archivo
27 | No se puede deshacer más.
28 | No se puede deshacer más. Pulsa atrás otra vez para salir.
29 | Archivo por defecto no encontrado.
30 | "No se puede leer el archivo por defecto"
31 | Elige un archivo para asociar a este widget
32 | Elige un archivo para abrir
33 | Elige un archivo para abrir desde la pantalla de inicio
34 | "El archivo abierto se ha guardado automáticamente y será abierto en el siguiente inicio"
35 |
36 |
37 |
--------------------------------------------------------------------------------
/Ted/res/values/arrays.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | - Classic
7 | - Negative
8 | - Matrix
9 | - Sky
10 | - Dracula
11 |
12 |
13 | - 0
14 | - 1
15 | - 2
16 | - 3
17 | - 4
18 |
19 |
20 |
21 |
22 | - 6 pt
23 | - 8 pt
24 | - 10 pt
25 | - 12 pt
26 | - 14 pt
27 | - 16 pt
28 | - 18 pt
29 | - 24 pt
30 | - 32 pt
31 | - 48 pt
32 |
33 |
34 | - 6
35 | - 8
36 | - 10
37 | - 12
38 | - 14
39 | - 16
40 | - 18
41 | - 24
42 | - 32
43 | - 48
44 |
45 |
46 |
47 |
48 | - Android / Linux / Unix
49 | - Windows / Symbian / Palm
50 | - Mac / iPhone
51 |
52 |
53 | - 0
54 | - 1
55 | - 2
56 |
57 |
58 |
59 |
60 | - 10
61 | - 25
62 | - 50
63 | - 100
64 | - 200
65 | - 500
66 |
67 |
68 |
69 |
70 | - 0
71 | - 1
72 | - 2
73 | - 3
74 | - 4
75 | - 5
76 | - 6
77 | - 7
78 | - 8
79 | - 9
80 | - 10
81 | - 11
82 | - 12
83 | - 13
84 | - 14
85 | - 15
86 |
87 |
88 |
89 |
90 | - ASCII
91 | - Latin 1
92 | - UTF 8
93 |
94 |
95 | - US-ASCII
96 | - ISO-8859-1
97 | - UTF-8
98 |
99 |
100 |
--------------------------------------------------------------------------------
/Ted/res/values-es/arrays.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | - Clásico
7 | - Negativo
8 | - Matrix
9 | - Azul
10 | - Drácula
11 |
12 |
13 | - 0
14 | - 1
15 | - 2
16 | - 3
17 | - 4
18 |
19 |
20 |
21 |
22 | - 6 pt
23 | - 8 pt
24 | - 10 pt
25 | - 12 pt
26 | - 14 pt
27 | - 16 pt
28 | - 18 pt
29 | - 24 pt
30 | - 32 pt
31 | - 48 pt
32 |
33 |
34 | - 6
35 | - 8
36 | - 10
37 | - 12
38 | - 14
39 | - 16
40 | - 18
41 | - 24
42 | - 32
43 | - 48
44 |
45 |
46 |
47 |
48 | - Android / Linux / Unix
49 | - Windows / Symbian / Palm
50 | - Mac / iPhone
51 |
52 |
53 | - 0
54 | - 1
55 | - 2
56 |
57 |
58 |
59 |
60 | - 10
61 | - 25
62 | - 50
63 | - 100
64 | - 200
65 | - 500
66 |
67 |
68 |
69 |
70 | - 0
71 | - 1
72 | - 2
73 | - 3
74 | - 4
75 | - 5
76 | - 6
77 | - 7
78 | - 8
79 | - 9
80 | - 10
81 | - 11
82 | - 12
83 | - 13
84 | - 14
85 | - 15
86 |
87 |
88 |
89 |
90 | - ASCII
91 | - Latin 1
92 | - UTF 8
93 |
94 |
95 | - US-ASCII
96 | - ISO-8859-1
97 | - UTF-8
98 |
99 |
100 |
101 |
--------------------------------------------------------------------------------
/Ted/res/values-sk/toasts.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Žiadne nedávne súbory na načítanie
5 | "Súbor už neexistuje, vymaže sa zo zoznamu nedávnych súborov."
6 | Súbor bol vymazaný zo zoznamu nedávnych súborov
7 | Nemožno otvoriť súbor, URI je neplatné
8 | Nemožno otvoriť súbor
9 | Nemožno načítať prehliadač súborov
10 | Nemožno otvoriť zoznam nedávnych súborov
11 | Nemožno načítať prehliadač súborov
12 | Nemožno načítať stránku s nastaveniami
13 | Nemožno načítať stránku o aplikácii
14 | Nemožno otvoriť súbor, nedostatok pamäte
15 | Nemožno otvoriť súbor (súbor je možno príliš veľký alebo poškodený)
16 | Nemožno uložiť, cesta nie je určená
17 | Nemožno uložiť do dočasného súboru
18 | Nemožno uložiť (chyba pri kopírovaní dočasného súbora do umiestnenia na uloženie)
19 | Nemožno uložiť (chyba pri kopírovaní dočasného súbora do umiestnenia na uloženie)
20 | Súbor bol uložený
21 | "Nemožno použiť tento priečinok, pretože nie je na zapisovanie"
22 | "Nemožno použiť tento súbor, pretože nie je na čítanie"
23 | Nenašla sa žiadna zhoda v súčasnom súbore
24 | Nenašla sa žiadna ďalšia zhoda v súčasnom súbore
25 | Zadajte text dp vyhľadávacieho riadku, ktorý chcete vyhľadať
26 | Názov súboru nesmie byť prázdny
27 | Nič na vrátenie.
28 | Nič na vrátenie. Stlačte tlačidlo Späť ešte raz pre ukončenie.
29 | Predvolený súbor nebol nájdený, skúste nastaviť nový v nastaveniach.
30 | "Nemožno otvoriť predvolený súbor, pretože nie je na čítanie"
31 | Vyberte súbor, ktorý chcete spojiť s touto novou miniaplikáciou
32 | Vyberte súbor na otvorenie
33 | Vyberte súbor, ktorý chcete otvoriť pri spustení Teda z domovskej obrazovky
34 | "Otvorený súbor sa uložil automaticky a bude otvorený pri ďalšom spustení"
35 |
36 |
--------------------------------------------------------------------------------
/Ted/src/fr/xgouchet/texteditor/TedFontActivity.java:
--------------------------------------------------------------------------------
1 | package fr.xgouchet.texteditor;
2 |
3 | import java.io.File;
4 | import java.util.LinkedList;
5 |
6 | import android.app.Activity;
7 | import android.content.Intent;
8 | import android.net.Uri;
9 | import android.os.Bundle;
10 | import android.view.KeyEvent;
11 | import android.view.View;
12 | import android.view.View.OnClickListener;
13 | import de.neofonie.mobile.app.android.widget.crouton.Crouton;
14 | import de.neofonie.mobile.app.android.widget.crouton.Style;
15 | import fr.xgouchet.androidlib.ui.activity.AbstractBrowsingActivity;
16 | import fr.xgouchet.texteditor.ui.adapter.FontListAdapter;
17 |
18 | public class TedFontActivity extends AbstractBrowsingActivity implements
19 | OnClickListener {
20 |
21 | /**
22 | * @see android.app.Activity#onCreate(android.os.Bundle)
23 | */
24 | protected void onCreate(Bundle savedInstanceState) {
25 | super.onCreate(savedInstanceState);
26 |
27 | setContentView(R.layout.layout_open);
28 | mExtWhiteList.add("ttf");
29 |
30 | // set default result
31 | setResult(RESULT_CANCELED, null);
32 |
33 | // buttons
34 | findViewById(R.id.buttonCancel).setOnClickListener(this);
35 |
36 | mListAdapter = new FontListAdapter(this, new LinkedList());
37 | }
38 |
39 | /**
40 | * @see fr.xgouchet.androidlib.ui.activity.BrowserActivity#onFileClick(java.io.File)
41 | */
42 | protected void onFileClick(File file) {
43 | if (setOpenResult(file))
44 | finish();
45 | }
46 |
47 | /**
48 | * @see fr.xgouchet.androidlib.ui.activity.BrowsingActivity#onFolderClick(java.io.File)
49 | */
50 | protected boolean onFolderClick(File folder) {
51 | return true;
52 | }
53 |
54 | /**
55 | * @see fr.xgouchet.androidlib.ui.activity.BrowsingActivity#onFolderViewFilled()
56 | */
57 | protected void onFolderViewFilled() {
58 |
59 | }
60 |
61 | /**
62 | * @see Activity#onKeyUp(int, KeyEvent)
63 | */
64 | public boolean onKeyUp(int keyCode, KeyEvent event) {
65 | if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
66 | // navigate to parent folder
67 | File parent = mCurrentFolder.getParentFile();
68 | if ((parent != null) && (parent.exists())) {
69 | fillFolderView(parent);
70 | return true;
71 | }
72 | }
73 | return super.onKeyUp(keyCode, event);
74 | }
75 |
76 | /**
77 | * @see android.view.View.OnClickListener#onClick(android.view.View)
78 | */
79 | public void onClick(View v) {
80 | if (v.getId() == R.id.buttonCancel) {
81 | setResult(RESULT_CANCELED);
82 | finish();
83 | }
84 | }
85 |
86 | /**
87 | * Set the result of this activity to open a file
88 | *
89 | * @param file
90 | * the file to return
91 | * @return if the result was set correctly
92 | */
93 | protected boolean setOpenResult(File file) {
94 | Intent result;
95 |
96 | if (!file.canRead()) {
97 | Crouton.showText(this, R.string.toast_file_cant_read, Style.ALERT);
98 | return false;
99 | }
100 |
101 | result = new Intent();
102 | result.setData(Uri.fromFile(file));
103 |
104 | setResult(RESULT_OK, result);
105 | return true;
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/Ted/res/values-fr/toasts.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | "Il n'y a pas de fichier recent à charger"
5 | "Le fichier selectionné n'existe plus"
6 | Fichier supprimé de la liste
7 | "Impossible d'ouvrir le fichier : adresse invalide"
8 | "Impossible d'ouvrir le fichier"
9 | "Impossible d'ouvrir l'explorateur de fichier"
10 | "Impossible d'ouvrir la liste de fichiers récents"
11 | "Impossible d'ouvrir l'explorateur de fichier"
12 | "Impossible d'ouvrir la page de paramètres"
13 | "Impossible d'ouvrir la page 'A propos'"
14 | "Impossible d'ouvrir le fichier, pas assez de mémoire"
15 | "Impossible d'ouvrir le fichier (le fichier est peut-être trop grand, ou corrompu)"
16 | "Impossible de sauver, le chemin d'accès est vide"
17 | "Impossible de sauvegarder le fichier temporaire"
18 | "Impossible de sauvegarder (erreur lors de la copie du fichier temporaire)"
19 | "Impossible de sauvegarder (erreur lors de la copie du fichier temporaire)"
20 | Fichier sauvegardé
21 | "Impossible d'ouvrir, ce dossier n'existe pas"
22 | "Impossible d'ouvrir, le fichier est protégé en lecture"
23 | "Can't use this file cause it isn't readable"
24 | "Pas de résultat dans ce fichier"
25 | "Pas d'autre résultat dans ce fichier"
26 | "Recherche vide"
27 | Le nom de fichier ne doit pas être vide
28 | Rien à annuler
29 | "Rien à annuler. Pressez retour pour quitter l'application"
30 | "Fichier par défaut non trouvé. Essayez d'en sélectionner un autre dans les options"
31 | "Impossible d'ouvrir, le fichier par défaut est protégé en lecture"
32 | Sélectionnez un fichier à associer à ce widget
33 | Sélectionnez un fichier à ouvrir
34 | Sélectionnez un fichier à ouvrir au démarrage de Ted
35 | "Le document a été sauvegardé et sera réouvert au prochain démarrage de Ted"
36 |
37 |
--------------------------------------------------------------------------------
/Ted/src/fr/xgouchet/texteditor/common/WidgetPrefs.java:
--------------------------------------------------------------------------------
1 | package fr.xgouchet.texteditor.common;
2 |
3 | import android.content.Context;
4 | import android.content.SharedPreferences;
5 | import android.content.SharedPreferences.Editor;
6 |
7 | public class WidgetPrefs {
8 |
9 | public final static String WIDGET_PREFERENCES = "fr.xgouchet.texteditor.widget";
10 |
11 | public final static String WIDGET_TARGET_PATH = "target_path_";
12 |
13 | public final static String WIDGET_READ_ONLY = "read_only_";
14 |
15 | public final static String WIDGET_PRESENT_KEY = "widget_present_";
16 |
17 | public String mTargetPath;
18 | public boolean mReadOnly;
19 |
20 | public WidgetPrefs() {
21 | mTargetPath = "";
22 | }
23 |
24 | /**
25 | * Loads the widget prefs from the shared preferences
26 | *
27 | * @param context
28 | * the current context
29 | * @param widgetId
30 | * this widget id
31 | * @return if the widget is still present
32 | */
33 | public boolean load(Context context, int widgetId) {
34 | String key;
35 | SharedPreferences prefs;
36 |
37 | prefs = context.getSharedPreferences(WIDGET_PREFERENCES,
38 | Context.MODE_PRIVATE);
39 |
40 | if (prefs != null) {
41 | key = WIDGET_TARGET_PATH + String.valueOf(widgetId);
42 | mTargetPath = prefs.getString(key, "");
43 |
44 | key = WIDGET_READ_ONLY + String.valueOf(widgetId);
45 | mReadOnly = prefs.getBoolean(key, false);
46 |
47 | key = WIDGET_PRESENT_KEY + String.valueOf(widgetId);
48 | return prefs.getBoolean(key, false);
49 | }
50 |
51 | return false;
52 | }
53 |
54 | /**
55 | * Store this widget prefs in the shared preferences
56 | *
57 | * @param context
58 | * the current context
59 | * @param widgetId
60 | * this widget id
61 | */
62 | public void store(Context context, int widgetId) {
63 | String key;
64 | SharedPreferences prefs;
65 | Editor edit;
66 |
67 | prefs = context.getSharedPreferences(WIDGET_PREFERENCES,
68 | Context.MODE_PRIVATE);
69 |
70 | if (prefs != null) {
71 | edit = prefs.edit();
72 |
73 | if (edit != null) {
74 | key = WIDGET_TARGET_PATH + String.valueOf(widgetId);
75 | edit.putString(key, mTargetPath);
76 |
77 | key = WIDGET_READ_ONLY + String.valueOf(widgetId);
78 | edit.putBoolean(key, mReadOnly);
79 |
80 | key = WIDGET_PRESENT_KEY + String.valueOf(widgetId);
81 | edit.putBoolean(key, true);
82 |
83 | edit.commit();
84 | }
85 | }
86 | }
87 |
88 | /**
89 | * Delete the data associated with a widget ID
90 | *
91 | * @param context
92 | * the current context
93 | * @param widgetId
94 | * the id to delete
95 | */
96 | public static void delete(Context context, int widgetId) {
97 | String key;
98 | SharedPreferences prefs;
99 | Editor edit;
100 |
101 | prefs = context.getSharedPreferences(WIDGET_PREFERENCES,
102 | Context.MODE_PRIVATE);
103 | if (prefs != null) {
104 | edit = prefs.edit();
105 |
106 | if (edit != null) {
107 | key = WIDGET_TARGET_PATH + String.valueOf(widgetId);
108 | edit.remove(key);
109 |
110 | key = WIDGET_READ_ONLY + String.valueOf(widgetId);
111 | edit.remove(key);
112 |
113 | key = WIDGET_PRESENT_KEY + String.valueOf(widgetId);
114 | edit.remove(key);
115 |
116 | edit.commit();
117 | }
118 | }
119 | }
120 | }
--------------------------------------------------------------------------------
/Ted/src/fr/xgouchet/texteditor/TedWidgetConfigActivity.java:
--------------------------------------------------------------------------------
1 | package fr.xgouchet.texteditor;
2 |
3 | import java.io.File;
4 |
5 | import android.appwidget.AppWidgetManager;
6 | import android.content.Intent;
7 | import android.os.Bundle;
8 | import android.view.View;
9 | import android.view.View.OnClickListener;
10 | import android.widget.CheckBox;
11 | import fr.xgouchet.androidlib.data.FileUtils;
12 | import fr.xgouchet.androidlib.ui.Toaster;
13 | import fr.xgouchet.androidlib.ui.activity.AbstractBrowsingActivity;
14 | import fr.xgouchet.texteditor.common.Constants;
15 | import fr.xgouchet.texteditor.common.WidgetPrefs;
16 |
17 | public class TedWidgetConfigActivity extends AbstractBrowsingActivity implements Constants, OnClickListener {
18 |
19 | /**
20 | * @see android.app.Activity#onCreate(android.os.Bundle)
21 | */
22 | protected void onCreate(Bundle savedInstanceState) {
23 | super.onCreate(savedInstanceState);
24 | setContentView(R.layout.layout_widget_config);
25 |
26 | setResult(RESULT_CANCELED, null);
27 |
28 | // buttons
29 | findViewById(R.id.buttonCancel).setOnClickListener(this);
30 |
31 | Toaster.showToast(this, R.string.toast_widget_select, false);
32 | }
33 |
34 | /**
35 | * @see android.app.Activity#onResume()
36 | */
37 | protected void onResume() {
38 | super.onResume();
39 |
40 | // get widget id
41 | Intent intent = getIntent();
42 | Bundle extras = intent.getExtras();
43 | if (extras != null) {
44 | mAppWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID,
45 | AppWidgetManager.INVALID_APPWIDGET_ID);
46 | }
47 | }
48 |
49 | /**
50 | * @see android.view.View.OnClickListener#onClick(android.view.View)
51 | */
52 | public void onClick(View v) {
53 | switch (v.getId()) {
54 | case R.id.buttonCancel:
55 | setResult(RESULT_CANCELED);
56 | finish();
57 | break;
58 | }
59 | }
60 |
61 | /**
62 | * @see fr.xgouchet.androidlib.ui.activity.BrowserActivity#onFileClick(java.io.File)
63 | */
64 | protected void onFileClick(File file) {
65 | if (file.canRead()) {
66 | mSelectedFile = file;
67 | setResultComplete();
68 | }
69 | }
70 |
71 | /**
72 | * @see fr.xgouchet.androidlib.ui.activity.BrowserActivity#onFolderClick(java.io.File)
73 | */
74 | protected boolean onFolderClick(File folder) {
75 | mSelectedFile = null;
76 | return true;
77 | }
78 |
79 | /**
80 | * @see fr.xgouchet.androidlib.ui.activity.BrowsingActivity#onFolderViewFilled()
81 | */
82 | protected void onFolderViewFilled() {
83 |
84 | }
85 |
86 | /**
87 | *
88 | */
89 | protected void setResultComplete() {
90 | AppWidgetManager appWidgetManager;
91 | Intent resultValue;
92 | WidgetPrefs prefs;
93 | boolean readOnly;
94 |
95 | readOnly = ((CheckBox) findViewById(R.id.readOnly)).isChecked();
96 |
97 | prefs = new WidgetPrefs();
98 | prefs.mTargetPath = FileUtils.getCanonizePath(mSelectedFile);
99 | prefs.mReadOnly = readOnly;
100 | prefs.store(this, mAppWidgetId);
101 |
102 | appWidgetManager = AppWidgetManager.getInstance(this);
103 | TedAppWidgetProvider.updateWidget(this, appWidgetManager, mAppWidgetId);
104 |
105 | //
106 | resultValue = new Intent();
107 | resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
108 | setResult(RESULT_OK, resultValue);
109 | finish();
110 | }
111 |
112 | /** the id of the widget being configured */
113 | protected int mAppWidgetId;
114 |
115 | /** the selected file */
116 | protected File mSelectedFile;
117 | }
118 |
--------------------------------------------------------------------------------
/Ted/src/fr/xgouchet/texteditor/TedOpenActivity.java:
--------------------------------------------------------------------------------
1 | package fr.xgouchet.texteditor;
2 |
3 | import java.io.File;
4 |
5 | import android.app.Activity;
6 | import android.content.Intent;
7 | import android.os.Bundle;
8 | import android.view.KeyEvent;
9 | import android.view.View;
10 | import android.view.View.OnClickListener;
11 | import de.neofonie.mobile.app.android.widget.crouton.Crouton;
12 | import de.neofonie.mobile.app.android.widget.crouton.Style;
13 | import fr.xgouchet.androidlib.ui.activity.AbstractBrowsingActivity;
14 | import fr.xgouchet.texteditor.common.Constants;
15 |
16 | public class TedOpenActivity extends AbstractBrowsingActivity implements
17 | OnClickListener, Constants {
18 |
19 | /**
20 | * @see android.app.Activity#onCreate(android.os.Bundle)
21 | */
22 | protected void onCreate(Bundle savedInstanceState) {
23 | super.onCreate(savedInstanceState);
24 | int request;
25 | Bundle extras;
26 |
27 | // Setup content view
28 | setContentView(R.layout.layout_open);
29 |
30 | // buttons
31 | findViewById(R.id.buttonCancel).setOnClickListener(this);
32 |
33 | // set default result
34 | setResult(RESULT_CANCELED, null);
35 |
36 | // show the title as toast
37 | extras = getIntent().getExtras();
38 | if (extras != null)
39 | request = extras.getInt(EXTRA_REQUEST_CODE);
40 | else
41 | request = -1;
42 |
43 | switch (request) {
44 | case REQUEST_OPEN:
45 | Crouton.showText(this, R.string.toast_open_select, Style.INFO);
46 | break;
47 | case REQUEST_HOME_PAGE:
48 | Crouton.showText(this, R.string.toast_home_page_select, Style.INFO);
49 | break;
50 | }
51 |
52 | }
53 |
54 | /**
55 | * @see Activity#onKeyUp(int, KeyEvent)
56 | */
57 | public boolean onKeyUp(int keyCode, KeyEvent event) {
58 | if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
59 | // navigate to parent folder
60 | File parent = mCurrentFolder.getParentFile();
61 | if ((parent != null) && (parent.exists())) {
62 | fillFolderView(parent);
63 | return true;
64 | }
65 | }
66 | return super.onKeyUp(keyCode, event);
67 | }
68 |
69 | /**
70 | * @see android.view.View.OnClickListener#onClick(android.view.View)
71 | */
72 | public void onClick(View v) {
73 | if (v.getId() == R.id.buttonCancel) {
74 | setResult(RESULT_CANCELED);
75 | finish();
76 | }
77 | }
78 |
79 | /**
80 | * @see fr.xgouchet.androidlib.ui.activity.BrowserActivity#onFolderClick(java.io.File)
81 | */
82 | protected boolean onFolderClick(File folder) {
83 | return true;
84 | }
85 |
86 | /**
87 | * @see fr.xgouchet.androidlib.ui.activity.BrowsingActivity#onFolderViewFilled()
88 | */
89 | protected void onFolderViewFilled() {
90 |
91 | }
92 |
93 | /**
94 | * @see fr.xgouchet.androidlib.ui.activity.BrowserActivity#onFileClick(java.io.File)
95 | */
96 | protected void onFileClick(File file) {
97 | if (setOpenResult(file))
98 | finish();
99 | }
100 |
101 | /**
102 | * Set the result of this activity to open a file
103 | *
104 | * @param file
105 | * the file to return
106 | * @return if the result was set correctly
107 | */
108 | protected boolean setOpenResult(File file) {
109 | Intent result;
110 |
111 | if (!file.canRead()) {
112 | Crouton.showText(this, R.string.toast_file_cant_read, Style.ALERT);
113 | return false;
114 | }
115 |
116 | result = new Intent();
117 | result.putExtra("path", file.getAbsolutePath());
118 |
119 | setResult(RESULT_OK, result);
120 | return true;
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/Ted/src/fr/xgouchet/texteditor/TedSaveAsActivity.java:
--------------------------------------------------------------------------------
1 | package fr.xgouchet.texteditor;
2 |
3 | import static fr.xgouchet.androidlib.ui.Toaster.showToast;
4 |
5 | import java.io.File;
6 |
7 | import android.content.Intent;
8 | import android.graphics.drawable.Drawable;
9 | import android.os.Bundle;
10 | import android.view.View;
11 | import android.view.View.OnClickListener;
12 | import android.widget.Button;
13 | import android.widget.EditText;
14 | import fr.xgouchet.androidlib.ui.activity.AbstractBrowsingActivity;
15 | import fr.xgouchet.texteditor.common.Constants;
16 |
17 | public class TedSaveAsActivity extends AbstractBrowsingActivity implements
18 | Constants, OnClickListener {
19 |
20 | /**
21 | * @see android.app.Activity#onCreate(android.os.Bundle)
22 | */
23 | protected void onCreate(Bundle savedInstanceState) {
24 | super.onCreate(savedInstanceState);
25 |
26 | // Setup content view
27 | setContentView(R.layout.layout_save_as);
28 |
29 | // buttons
30 | findViewById(R.id.buttonCancel).setOnClickListener(this);
31 | findViewById(R.id.buttonOk).setOnClickListener(this);
32 | ((Button) findViewById(R.id.buttonOk)).setText(R.string.ui_save);
33 |
34 | // widgets
35 | mFileName = (EditText) findViewById(R.id.editFileName);
36 |
37 | // drawables
38 | mWriteable = getResources().getDrawable(R.drawable.folder_rw);
39 | mLocked = getResources().getDrawable(R.drawable.folder_r);
40 | }
41 |
42 | /**
43 | * @see android.view.View.OnClickListener#onClick(android.view.View)
44 | */
45 | public void onClick(View v) {
46 | switch (v.getId()) {
47 | case R.id.buttonCancel:
48 | setResult(RESULT_CANCELED);
49 | finish();
50 | break;
51 | case R.id.buttonOk:
52 | if (setSaveResult())
53 | finish();
54 | }
55 | }
56 |
57 | /**
58 | * @see fr.xgouchet.androidlib.ui.activity.BrowserActivity#onFileClick(java.io.File)
59 | */
60 | protected void onFileClick(File file) {
61 | if (file.canWrite())
62 | mFileName.setText(file.getName());
63 | }
64 |
65 | /**
66 | * @see fr.xgouchet.androidlib.ui.activity.BrowserActivity#onFolderClick(java.io.File)
67 | */
68 | protected boolean onFolderClick(File folder) {
69 | return true;
70 | }
71 |
72 | /**
73 | * @see fr.xgouchet.androidlib.ui.activity.BrowsingActivity#onFolderViewFilled()
74 | */
75 | protected void onFolderViewFilled() {
76 |
77 | }
78 |
79 | /**
80 | * Sets the result data when the user presses save
81 | *
82 | * @return if the result is OK (if not, it means the user must change its
83 | * selection / input)
84 | */
85 | protected boolean setSaveResult() {
86 | Intent result;
87 | String fileName;
88 |
89 | if ((mCurrentFolder == null) || (!mCurrentFolder.exists())) {
90 | showToast(this, R.string.toast_folder_doesnt_exist, true);
91 | return false;
92 | }
93 |
94 | if (!mCurrentFolder.canWrite()) {
95 | showToast(this, R.string.toast_folder_cant_write, true);
96 | return false;
97 | }
98 |
99 | fileName = mFileName.getText().toString();
100 | if (fileName.length() == 0) {
101 | showToast(this, R.string.toast_filename_empty, true);
102 | return false;
103 | }
104 |
105 | result = new Intent();
106 | result.putExtra("path", mCurrentFolder.getAbsolutePath()
107 | + File.separator + fileName);
108 |
109 | setResult(RESULT_OK, result);
110 | return true;
111 | }
112 |
113 | /** the edit text input */
114 | protected EditText mFileName;
115 |
116 | /** */
117 | protected Drawable mWriteable;
118 | /** */
119 | protected Drawable mLocked;
120 |
121 | }
122 |
--------------------------------------------------------------------------------
/Ted/src/fr/xgouchet/texteditor/undo/TextChangeInsert.java:
--------------------------------------------------------------------------------
1 | package fr.xgouchet.texteditor.undo;
2 |
3 | import fr.xgouchet.texteditor.BuildConfig;
4 | import android.text.Editable;
5 | import android.util.Log;
6 |
7 | public class TextChangeInsert implements TextChange {
8 |
9 | protected StringBuffer mSequence;
10 | protected int mStart;
11 |
12 | /**
13 | * @param seq
14 | * the initial sequence
15 | * @param start
16 | * the start index for this sequence
17 | *
18 | */
19 | public TextChangeInsert(CharSequence seq, int start) {
20 | mSequence = new StringBuffer();
21 | mSequence.append(seq);
22 | mStart = start;
23 | }
24 |
25 | /**
26 | * @see fr.xgouchet.texteditor.undo.TextChange#getCaret()
27 | */
28 | public int getCaret() {
29 | if (mSequence.toString().contains(" "))
30 | return -1;
31 | if (mSequence.toString().contains("\n"))
32 | return -1;
33 | return mStart + mSequence.length();
34 | }
35 |
36 | /**
37 | * @see fr.xgouchet.texteditor.undo.TextChange#append(java.lang.CharSequence)
38 | */
39 | public void append(CharSequence seq) {
40 | mSequence.append(seq);
41 | }
42 |
43 | /**
44 | * @see fr.xgouchet.texteditor.undo.TextChange#canMergeChangeBefore(java.lang.CharSequence,
45 | * int, int, int)
46 | */
47 | public boolean canMergeChangeBefore(CharSequence s, int start, int count, int after) {
48 |
49 | CharSequence sub;
50 | boolean append, replace;
51 |
52 | if (mSequence.toString().contains(" "))
53 | return false;
54 | if (mSequence.toString().contains("\n"))
55 | return false;
56 |
57 | sub = s.subSequence(start, start + count);
58 | append = (start == mStart + mSequence.length());
59 | replace = (start == mStart) && (after >= mSequence.length())
60 | && (sub.toString().startsWith(mSequence.toString()));
61 |
62 | if (append) {
63 | // mSequence.append(sub);
64 | return true;
65 | }
66 |
67 | if (replace) {
68 | // mSequence = new StringBuffer();
69 | // mSequence.append(sub);
70 | return true;
71 | }
72 | return false;
73 | }
74 |
75 | /**
76 | * @see fr.xgouchet.texteditor.undo.TextChange#canMergeChangeAfter(java.lang.CharSequence,
77 | * int, int, int)
78 | */
79 | public boolean canMergeChangeAfter(CharSequence s, int start, int before, int count) {
80 | CharSequence sub;
81 | boolean append, replace;
82 |
83 | if (mSequence.toString().contains(" "))
84 | return false;
85 | if (mSequence.toString().contains("\n"))
86 | return false;
87 |
88 | sub = s.subSequence(start, start + count);
89 | append = (start == mStart + mSequence.length());
90 | replace = (start == mStart) && (count >= mSequence.length())
91 | && (sub.toString().startsWith(mSequence.toString()));
92 |
93 | if (append) {
94 | mSequence.append(sub);
95 | return true;
96 | }
97 |
98 | if (replace) {
99 | mSequence = new StringBuffer();
100 | mSequence.append(sub);
101 | return true;
102 | }
103 |
104 | return false;
105 | }
106 |
107 | /**
108 | * @see fr.xgouchet.texteditor.undo.TextChange#undo(java.lang.String)
109 | */
110 | public int undo(Editable s) {
111 | if (BuildConfig.DEBUG)
112 | Log.i(TAG, "Undo Insert : deleting " + mStart + " to " + (mStart + mSequence.length()));
113 | s.replace(mStart, mStart + mSequence.length(), "");
114 | return mStart;
115 | }
116 |
117 | /**
118 | * @see java.lang.Object#toString()
119 | */
120 | public String toString() {
121 | return "+\"" + mSequence.toString().replaceAll("\n", "~") + "\" @" + mStart;
122 | }
123 |
124 | }
125 |
--------------------------------------------------------------------------------
/Ted/res/values/history.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 1.8 (10 nov 2012)
7 | "- Bug fixed : current file / last loaded file
8 | - Updated notification system
9 | - Possibility to modify the text font used by the editor (You can use any ttf font located on your device's internal and/or external storage)"
10 |
11 |
12 | 1.7 (16 july 2012)
13 | "- Bug fixed : Save/Save As crash on some phone
14 | - Added option to disable autosave on existing files"
15 |
16 |
17 | 1.6 (9 july 2012)
18 | "- Added the Auto Save feature
19 | - fixed the bug with Search case "
20 |
21 |
22 | 1.5 (21 june 2012)
23 | "- Adapted for Ice Cream Sandwich
24 | - Improved the Undo option (bugs with suggestions)
25 | - Added a Home Screen Widgets (shortcut to favorite files)
26 | - Added option to open a file by default when starting Ted
27 | - New Graphics (all made by myself ^^)"
28 |
29 |
30 | 1.3 (5 may 2012)
31 | "- Added an undo option (check the settings)
32 | - Added some performance tweaks"
33 |
34 |
35 | 1.2 (18 apr. 2012)
36 | "- Fixed the scroll bug since last update
37 | - fixed the fling options in the settings (option was always active)"
38 |
39 |
40 | 1.1 (10 apr. 2012)
41 | "- Fixed the crash at start caused by the last update
42 | - Added Fling to Scroll (launches the scroll to navigate in large files)
43 | - Display the active line
44 | - Added new color theme (ask for more if needed)"
45 | 1.0 (27 feb. 2012)
46 | "- Brand new release version
47 | - Supports multiple encoding (including UTF-8)
48 | - Prevent data loss when saving really big files (note that Ted is not meant to open big files though)
49 | - Added new color theme (ask for more if needed)
50 | - Replaced the autosave with a warning and popup (prevent saving unwanted changes)"
51 | βetα 0.9 (7 jan. 2010)
52 | "- Bug fixed : severall crash on start
53 | - Added a search tool
54 | - Ted is listed when opening html, rss, css, php and xml files from any file browser (ask for other types if needed)"
55 | βetα 0.8 (23 dec. 2010)
56 | "- Automatic save can be disabled in the settings"
57 | βetα 0.7 (19 dec. 2010)
58 | "- App can be installed on the SD Card (on Android 2.2)
59 | - Automatic detection of end of line in opened files, possibility to define a default end of line for new files
60 | - Bigger dialog boxes
61 | - Bug fixed when openning big files"
62 | βetα 0.6 (8 dec. 2010)
63 | "- Possibility to change text size in the settings.
64 | - Possibility to open read-only text files from other location than the SD card
65 | - Added a backup function for unsaved text "
66 | βetα 0.5 (29 nov. 2010)
67 | "- Bug fixed while opening some files
68 | - New Graphics"
69 | βetα 0.4 (27 nov. 2010)
70 | "- Remembers the files opened recently (number of recent files can be changed)
71 | - display lines numbers (can be changed in the settings)
72 | - automatically break lines to keep a width of one page (can be changed in the settings)"
73 | βetα 0.3 (25 nov. 2010)
74 | "- Bug fixed : crash when trying to open online files"
75 | βetα 0.2 (13 nov. 2010)
76 | "- Open existing files - Save and save as"
77 |
78 |
--------------------------------------------------------------------------------
/Ted/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Ted
5 | Ted (Text Editor)
6 |
7 |
8 | Ted Internal Permission
9 |
10 |
11 | Ted - %1$s
12 | Ted - %1$s *
13 | Ted - [%1$s]
14 | Ted - Save as ...
15 | Ted - Open Recent
16 | Ted - Settings
17 | Ted - About ...
18 | Ted - Text Font
19 |
20 |
21 | Display
22 | Other
23 | Saving
24 | Undo
25 | Search
26 | Miscellaneous
27 | Show line numbers
28 | Word wrap
29 | Change text font
30 | Text size
31 | Color theme
32 | End of lines
33 | Maximum recent files
34 | Search wrap
35 | Search match case
36 | Encoding
37 | Fling to scroll faster
38 | Allow undo
39 | Maximum undo history
40 | Use the back button to undo previous modifications
41 | Use a default file
42 | Auto Save
43 | Overwrite existing files
44 | Automatically saves the file being edited when the app goes in background
45 | Display the line number at the left of the page
46 | Lines will break in new lines if they are too wide for the screen
47 | Uncheck if you have performance issues
48 | Select a file to open when you launch Ted from your home screen
49 | Auto save will overwrite existing files
50 | Auto save will only work with new files
51 |
52 |
53 | New
54 | Open
55 | Recent files
56 | Save
57 | Save as
58 | Settings
59 | About
60 | Search
61 | Undo
62 | Quit
63 |
64 |
65 | "Do you want to save your document? \nAny unsaved changes will be lost. "
66 | Save
67 | Delete
68 | "Don't save"
69 | Cancel
70 | File name
71 | Search
72 | Artistic Licence
73 | History
74 | Open as read only
75 |
76 |
77 | "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas porttitor neque semper sem fermentum pretium. Sed pharetra dui faucibus massa malesuada in condimentum mi gravida."
78 | "All icons for this app were created and belong to the author of the app : Xavier Gouchet (android@xgouchet.fr)."
79 |
80 |
--------------------------------------------------------------------------------
/Ted/res/values-sk/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Ted
5 | Ted (Textový editor)
6 |
7 |
8 | Interné povolenie Ted
9 |
10 |
11 | Ted - %1$s
12 | Ted - %1$s *
13 | Ted - [%1$s]
14 | Ted - Uložiť ako...
15 | Ted - Otvoriť nedávne
16 | Ted - Nastavenia
17 | Ted - O aplikácii ...
18 | Ted - Písmo textu
19 |
20 |
21 | Zobrazenie
22 | Ostatné
23 | Ukladanie
24 | Krok späť
25 | Hľadať
26 | Rôzne
27 | Zobraziť čísla riadkov
28 | Zalomiť text
29 | Zmeniť písmo textu
30 | Veľkosť písma
31 | Farebná téma
32 | Koniec riadkov
33 | Maximálny počet nedávnych súborov
34 | Zalomiť hľadanie
35 | Hľadať veľké a malé písmená
36 | Kódovanie
37 | Vrhnúť pre rýchlejší posun
38 | Povoliť krok späť
39 | Maximálna história pre krok späť
40 | Použiť tlačidlo Späť pre vrátenie predchádzajúcej úpravy
41 | Použiť predvolený súbor
42 | Automatické ukladanie
43 | Prepísať existujúce súbory
44 | Automaticky uložiť editovaný súbor, keď je aplikácia prepnutá do pozadia
45 | Zobraziť číslo riadku v ľavej časti stránky
46 | Riadky sa rozdelia do nových riadkov, ak sú príliš široké na obrazovke
47 | Zakážte, ak máte problémy s výkonom
48 | Vybrať súbor, ktorý chcete otvoriť pri spustení Teda z domovskej obrazovky
49 | Automatické ukladanie prepíše existujúce súbory
50 | Automatické ukladanie bude pracovať iba s novými súbormi
51 |
52 |
53 | Nový
54 | Otvoriť
55 | Nedávne súbory
56 | Uložiť
57 | Uložiť ako
58 | Nastavenia
59 | O aplikácii
60 | Hľadať
61 | Krok späť
62 | Ukončiť
63 |
64 |
65 | Chcete uložiť dokument?\nAkékoľvek neuložené zmeny budú stratené.
66 | Uložiť
67 | Vymazať
68 | Neukladať
69 | Zrušiť
70 | Názov súboru
71 | Hľadať
72 | Umelecká licencia
73 | História
74 | Otvoriť len na čítanie
75 |
76 |
77 | "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas porttitor neque semper sem fermentum pretium. Sed pharetra dui faucibus massa malesuada in condimentum mi gravida."
78 | "Všetky ikony pre túto aplikáciu boli vytvorené a patria autorovi aplikácie: Xavier Gouchet (android@xgouchet.fr)."
79 |
80 |
--------------------------------------------------------------------------------
/Ted/res/values-fr/history.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 1.8 (10 nov 2012)
7 | "- Bug fixed : problèmes avec la sauvegarde du dernier fichier ouvert
8 | - Mise a jour du système de notifications
9 | - Possibilité de changer la police d'écriture utilisée par l'éditeur (Vous pouvez importer n'importe quel fichier TTF situé sur l'appareil et/ou la carte mémoire)"
10 |
11 |
12 | 1.7 (16 juillet 2012)
13 | "- Correction de bug lors de la sauvegarde sur certains appareils \n
14 | - Option pour désactiver la sauvegarde automatique sur les fichiers existants \n"
15 |
16 |
17 | 1.6 (9 juillet 2012)
18 | "- Ajout de la sauvegarde automatique \n
19 | - correction de la recherche sensible à la casse \n"
20 |
21 |
22 | 1.5 (21 juin 2012)
23 | "- Adaptation à Ice Cream Sandwich \n
24 | - Amélioration de l'option Annuler (bugs avec les suggestions) \n
25 | - Ajout d'un widget (raccourci vers un fichier)\n
26 | - Ajout d'une option pour ouvrir automatiquement un fichier favori au démarrage de l'application\n
27 | - Refonte graphique (nouveaux icones réalisés par votre serviteur ^^) \n"
28 |
29 |
30 | 1.3 (5 mai 2012)
31 | "- Ajout d'une option Annuler\n
32 | - Optimisation des performances"
33 | 1.2 (18 avr. 2012)
34 | "- Correction du bug de défilement depuis la dernière MAJ\n
35 | - correction de l'option défilement rapide (l'option restait activée quelle que soit la valeur dans les préferences)"
36 | 1.1 (10 avr. 2012)
37 | "- Correction du crash du à la dernière mise à jour\n
38 | - Ajout d'un défilement par lancé (pour naviguer dans les longs fichiers)\n
39 | - Affiche la ligne active\n
40 | - Ajout de thèmes de couleurs (n'hesitez pas à en demander plus)"
41 | 1.0 (27 fev. 2012)
42 | "- Refonte du logiciel dans une toute nouvelle version\n
43 | - Support d'encodages multiples (entre autres UTF-8)\n
44 | - Evite la perte de donnée en cas de crash de sauvegarde sur les gros fichiers (cela dit, Ted n'est pas fait pour manipuler des fichiers trops lourds)\n
45 | - Ajout de thèmes de couleurs (n'hesitez pas à en demander plus)\n
46 | - Replaced the autosave with a warning and popup (prevent saving unwanted changes)"
47 | βetα 0.9 (7 jan. 2010)
48 | "- Bug corrigé : différents crash à l'ouverture \n
49 | - Ajout de recherche de texte dans le fichier ouvert \n
50 | - Ted est utilisable depuis un explorateur de fichiers pour ouvrir les fichiers html, rss, css, php et xml (demandez s'il vous en manque d'autres)"
51 | βetα 0.8 (23 dec. 2010)
52 | "- La sauvegarde automatique peut être désactivée dans les paramètres"
53 | βetα 0.7 (19 dec. 2010)
54 | "- Possibilité d'installer l'application sur carte SD (Android 2.2) \n
55 | - Détection automatique des fins de lignes des fichiers ouverts, possibilité de définir un format pour les nouveaux fichiers \n
56 | - Boites de dialogue plus grandes \n
57 | - Bug lors de l'ouverture de fichier trop grands corrigés \n"
58 | βetα 0.6 (8 dec. 2010)
59 | "- Possibilité de changer la taille du texte dans les parametres. \n
60 | - Possibilité d'ouvrir des fichiers textes en lecture seule, ailleurs que sur la carte SD \n
61 | - Un texte non sauvé est gardé en mémoire lorsque l'application se ferme et s'ouvre à la prochaine utilisation de l'éditeur \n"
62 | βetα 0.5 (29 nov. 2010)
63 | "- Bug à l'ouverture de certains fichiers corrigé \n
64 | - Nouveaux icones "
65 | βetα 0.4 (27 nov. 2010)
66 | "- Enregistrement des fichiers recemment ouvert (nombre de fichier récents paramétrable) \n
67 | - Affichage des numeros de lignes (parametrable) \n
68 | - Coupure automatique des lignes pour garder le texte sur une page horizontale (paramétrable) "
69 | βetα 0.3 (25 nov. 2010)
70 | "- Bug sur les fichiers en ligne corrigé"
71 | βetα 0.2 (13 nov. 2010)
72 | "- Ouvrir un fichier existant \n
73 | - Sauver et Sauver sous"
74 |
75 |
--------------------------------------------------------------------------------
/Ted/res/values-fr/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Ted
5 | Ted (Editeur de texte)
6 | Ted - Permission Interne
7 |
8 |
9 | Ted - Sauver sous ...
10 | Ted - Documents récents
11 | Ted - Paramètres
12 | Ted - A propos ...
13 | Ted - Police
14 | Ted - %1$s
15 | Ted - %1$s *
16 | Ted - [%1$s]
17 |
18 |
19 | Affichage
20 | Autres
21 | Sauvegarde
22 | Recherche
23 | Historique
24 | Divers
25 | Changer la police
26 | Afficher les numéros de ligne
27 | Coupure de lignes automatique
28 | Taille du texte
29 | Thèmes de couleurs
30 | Fin de lignes
31 | Fichiers récents
32 | Recherche en boucle
33 | Recherche sensible à la casse
34 | Encodage
35 | Défilement par lancé
36 | "Activer l'option \"Annuler\""
37 | Nombre maximum de changements enregistrés
38 | Utiliser le bouton retour pour annuler la dernière opération
39 | Utiliser un fichier par défaut
40 | Sauvegarde auto
41 | Ecraser les fichiers existants
42 | "Sauvegarde automatique du fichier en cours lorsque l'application passe en arrière plan"
43 | Les numéros de lignes sont affichés en début de ligne
44 | "Les lignes trop longues sont ajustées à la taille de l'écran"
45 | "Décocher l'option en cas de problèmes de performances"
46 | Selectionner un fichier à ouvrir au démarrage de Ted
47 | "La sauvegarde automatique ecrasera les fichiers existants"
48 | "La sauvegarde automatique ne fonctionnera que pour les nouveaux fichiers"
49 |
50 |
51 | Nouveau
52 | Ouvrir
53 | Documents récents
54 | Sauver
55 | Sauver sous
56 | Paramètres
57 | A propos
58 | Rechercher
59 | Annuler
60 | Quitter
61 |
62 |
63 | "Voulez vous sauver votre document? \nTout changement non sauvé sera perdu. "
64 | Sauver
65 | "Ne pas sauver"
66 | Annuler
67 | Supprimer
68 | Nom du fichier
69 | Rechercher
70 | Historique
71 | Licence Artistique
72 | Ouvrir en lecture seule
73 |
74 |
75 | "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas porttitor neque semper sem fermentum pretium. Sed pharetra dui faucibus massa malesuada in condimentum mi gravida."
76 | "Toutes les icônes de cette application ont été créées et appartiennent à l'auteur de l'application : Xavier Gouchet (android@xgouchet.fr)."
77 |
78 |
--------------------------------------------------------------------------------
/Ted/res/values-es/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Ted
5 | Ted (Editor de texto)
6 |
7 |
8 | Ted Internal Permission
9 |
10 |
11 | Ted - %1$s
12 | Ted - %1$s *
13 | Ted - [%1$s]
14 | Ted - Guardar como ...
15 | Ted - Abrir reciente
16 | Ted - Configuración
17 | Ted - Acerca de ...
18 | Ted - Fuente del texto
19 |
20 |
21 | Display
22 | Otros
23 | Guardado
24 | Configurar deshacer
25 | Búsqueda
26 | Configuración avanzada
27 | Mostrar números en cada línea
28 | Agrupar líneas
29 | Cambiar fuente del texto
30 | Tamaño del texto
31 | Tema de la interfaz
32 | Retorno de carro
33 | Máximo número de archivos recientes
34 | Buscar en todo el documento
35 | Respetar mayúsculas y minúsculas
36 | Codificación
37 | Efecto de scroll
38 | Habilitar deshacer
39 | Historial máximo para deshacer
40 | Asignar "deshacer" al botón de atrás
41 | Usar un archivo por defecto
42 | Autoguardado
43 | Sobreescribir archivos existentes
44 | Salva automáticamente si la aplicación pasa a segundo plano
45 | Se muestran los números de cada línea a la izquierda de la página
46 | Las líneas se ajustarán para que quepan en la pantalla
47 | Desmarcar si se experimentan problemas de rendimiento
48 | Selecciona un archivo para abrir cada vez que se ejecute Ted
49 | El autoguardado sobreescribirá los archivos existentes
50 | El autoguardado sólo funcionará con los nuevos archivos
51 |
52 |
53 | Nuevo
54 | Abrir
55 | Abrir reciente
56 | Guardar
57 | Guardar como
58 | Configuración
59 | Acerca de
60 | Buscar
61 | Deshacer
62 | Salir
63 |
64 |
65 | "¿Quieres guardar el archivo? \nSe perderán los cambios no guardados. "
66 | Guardar
67 | Borrar
68 | "Descartar"
69 | Cancelar
70 | Nombre de archivo
71 | Buscar
72 | Licencia artística
73 | Historial
74 | Abrir como sólo lectura
75 |
76 |
77 | "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas porttitor neque semper sem fermentum pretium. Sed pharetra dui faucibus massa malesuada in condimentum mi gravida."
78 | "Todos los iconos de esta aplicación fueron creados por el desarrollador de la misma. Derechos de propiedad intelectual reservados por Xavier Gouchet (android@xgouchet.fr)."
79 |
80 |
81 |
--------------------------------------------------------------------------------
/Ted/src/fr/xgouchet/texteditor/TedOpenRecentActivity.java:
--------------------------------------------------------------------------------
1 | package fr.xgouchet.texteditor;
2 |
3 | import java.io.File;
4 | import java.util.ArrayList;
5 |
6 | import android.app.Activity;
7 | import android.content.Intent;
8 | import android.os.Bundle;
9 | import android.view.ContextMenu;
10 | import android.view.ContextMenu.ContextMenuInfo;
11 | import android.view.Menu;
12 | import android.view.MenuItem;
13 | import android.view.View;
14 | import android.view.View.OnClickListener;
15 | import android.widget.AdapterView;
16 | import android.widget.AdapterView.AdapterContextMenuInfo;
17 | import android.widget.AdapterView.OnItemClickListener;
18 | import android.widget.ListAdapter;
19 | import android.widget.ListView;
20 | import fr.xgouchet.androidlib.ui.Toaster;
21 | import fr.xgouchet.texteditor.common.Constants;
22 | import fr.xgouchet.texteditor.common.RecentFiles;
23 | import fr.xgouchet.texteditor.ui.adapter.PathListAdapter;
24 |
25 | public class TedOpenRecentActivity extends Activity implements Constants, OnClickListener,
26 | OnItemClickListener {
27 |
28 | /**
29 | * @see android.app.Activity#onCreate(android.os.Bundle)
30 | */
31 | protected void onCreate(Bundle savedInstanceState) {
32 | super.onCreate(savedInstanceState);
33 |
34 | // Setup content view
35 | setContentView(R.layout.layout_open);
36 |
37 | // buttons
38 | findViewById(R.id.buttonCancel).setOnClickListener(this);
39 |
40 | // widgets
41 | mFilesList = (ListView) findViewById(android.R.id.list);
42 | mFilesList.setOnItemClickListener(this);
43 | mFilesList.setOnCreateContextMenuListener(this);
44 | }
45 |
46 | /**
47 | * @see android.app.Activity#onResume()
48 | */
49 | protected void onResume() {
50 | super.onResume();
51 |
52 | fillRecentFilesView();
53 | }
54 |
55 | /**
56 | * @see android.app.Activity#onCreateContextMenu(android.view.ContextMenu,
57 | * android.view.View, android.view.ContextMenu.ContextMenuInfo)
58 | */
59 | public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
60 | super.onCreateContextMenu(menu, v, menuInfo);
61 | AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo;
62 | mContextPath = (String) mFilesList.getAdapter().getItem(info.position);
63 |
64 | menu.setHeaderTitle(mContextPath);
65 | menu.add(Menu.NONE, 0, Menu.NONE, R.string.ui_delete);
66 | }
67 |
68 | /**
69 | * @see android.app.Activity#onContextItemSelected(android.view.MenuItem)
70 | */
71 | public boolean onContextItemSelected(MenuItem item) {
72 |
73 | RecentFiles.removePath(mContextPath);
74 | RecentFiles.saveRecentList(getSharedPreferences(PREFERENCES_NAME, MODE_PRIVATE));
75 |
76 | fillRecentFilesView();
77 | Toaster.showToast(this, R.string.toast_recent_files_deleted, false);
78 |
79 | return true;
80 | }
81 |
82 | /**
83 | * @see android.view.View.OnClickListener#onClick(android.view.View)
84 | */
85 | public void onClick(View v) {
86 | switch (v.getId()) {
87 | case R.id.buttonCancel:
88 | setResult(RESULT_CANCELED);
89 | finish();
90 | break;
91 | }
92 | }
93 |
94 | /**
95 | * @see android.widget.AdapterView.OnItemClickListener#onItemClick(android.widget.AdapterView,
96 | * android.view.View, int, long)
97 | */
98 | public void onItemClick(AdapterView> parent, View view, int position, long id) {
99 | String path;
100 |
101 | path = mList.get(position);
102 |
103 | if (setOpenResult(new File(path))) {
104 | finish();
105 | } else {
106 | RecentFiles.removePath(path);
107 | RecentFiles.saveRecentList(getSharedPreferences(PREFERENCES_NAME, MODE_PRIVATE));
108 | ((PathListAdapter) mListAdapter).notifyDataSetChanged();
109 | Toaster.showToast(this, R.string.toast_recent_files_invalid, true);
110 | }
111 |
112 | }
113 |
114 | /**
115 | * Fills the files list with the recent files
116 | *
117 | */
118 | protected void fillRecentFilesView() {
119 | mList = RecentFiles.getRecentFiles();
120 |
121 | if (mList.size() == 0) {
122 | setResult(RESULT_CANCELED);
123 | finish();
124 | return;
125 | }
126 |
127 | // create string list adapter
128 | mListAdapter = new PathListAdapter(this, mList);
129 |
130 | // set adpater
131 | mFilesList.setAdapter(mListAdapter);
132 | }
133 |
134 | /**
135 | * Set the result of this activity to open a file
136 | *
137 | * @param file
138 | * the file to return
139 | * @return if the result was set correctly
140 | */
141 | protected boolean setOpenResult(File file) {
142 | Intent result;
143 |
144 | if ((file == null) || (!file.isFile()) || (!file.canRead())) {
145 | return false;
146 | }
147 |
148 | result = new Intent();
149 | result.putExtra("path", file.getAbsolutePath());
150 |
151 | setResult(RESULT_OK, result);
152 | return true;
153 | }
154 |
155 | protected String mContextPath;
156 |
157 | /** the dialog's list view */
158 | protected ListView mFilesList;
159 | /** The list adapter */
160 | protected ListAdapter mListAdapter;
161 |
162 | /** the list of recent files */
163 | protected ArrayList mList;
164 | }
165 |
--------------------------------------------------------------------------------
/Ted/src/fr/xgouchet/texteditor/undo/TextChangeWatcher.java:
--------------------------------------------------------------------------------
1 | package fr.xgouchet.texteditor.undo;
2 |
3 | import java.util.Stack;
4 |
5 | import android.text.Editable;
6 | import android.util.Log;
7 | import fr.xgouchet.texteditor.BuildConfig;
8 | import fr.xgouchet.texteditor.common.Constants;
9 | import fr.xgouchet.texteditor.common.Settings;
10 |
11 | public class TextChangeWatcher implements Constants {
12 |
13 | /**
14 | *
15 | */
16 | public TextChangeWatcher() {
17 | mChanges = new Stack();
18 | }
19 |
20 | /**
21 | * Undo the last operation
22 | *
23 | * @param text
24 | * the text to undo on
25 | * @return the caret position
26 | */
27 | public int undo(Editable text) {
28 | pushCurrentChange();
29 |
30 | if (mChanges.size() == 0) {
31 | if (BuildConfig.DEBUG)
32 | Log.i(TAG, "Nothing to undo");
33 | return -1;
34 | }
35 |
36 | TextChange change = mChanges.pop();
37 | if (change != null)
38 | return change.undo(text);
39 | else if (BuildConfig.DEBUG)
40 | Log.w(TAG, "Null change ?!");
41 |
42 | return -1;
43 | }
44 |
45 | /**
46 | * A change to the text {@linkplain s} will be made, where the
47 | * {@linkplain count} characters starting at {@linkplain start} will be
48 | * replaced by {@linkplain after} characters
49 | *
50 | * @param s
51 | * the sequence being changed
52 | * @param start
53 | * the start index
54 | * @param count
55 | * the number of characters that will change
56 | * @param after
57 | * the number of characters that will replace the old ones
58 | *
59 | */
60 | public void beforeChange(CharSequence s, int start, int count, int after) {
61 | if ((mCurrentChange != null)
62 | && (mCurrentChange.canMergeChangeBefore(s, start, count, after))) {
63 | } else {
64 | if (count == 0) {
65 | // no existing character changed
66 | // ignore, will be processed after
67 | } else if (after == 0) {
68 | // existing character replaced by none => delete
69 | processDelete(s, start, count);
70 | } else {
71 | // n chars replaced by m other chars => replace
72 | // replace is a delete AND an insert...
73 | processDelete(s, start, count);
74 | }
75 | }
76 | }
77 |
78 | /**
79 | * A change to the text {@linkplain s} has been made, where the
80 | * {@linkplain count} characters starting at {@linkplain start} have
81 | * replaced the substring of length {@linkplain before}
82 | *
83 | * @param s
84 | * the sequence being changed
85 | * @param start
86 | * the start index
87 | * @param before
88 | * the number of character that were replaced
89 | * @param count
90 | * the number of characters that will change
91 | */
92 | public void afterChange(CharSequence s, int start, int before, int count) {
93 | if ((mCurrentChange != null)
94 | && (mCurrentChange.canMergeChangeAfter(s, start, before, count))) {
95 |
96 | } else {
97 | if (before == 0) {
98 | // 0 charactes replaced by count => insert
99 | processInsert(s, start, count);
100 | } else if (count == 0) {
101 | // existing character replaced by none => delete, already done
102 | // before
103 | } else {
104 | // n chars replaced by m other chars => replace
105 | // replace is a delete AND an insert...
106 | processInsert(s, start, count);
107 | }
108 | }
109 |
110 | // printStack();
111 | }
112 |
113 | /**
114 | * @param s
115 | * the sequence being modified
116 | * @param start
117 | * the first character index
118 | * @param count
119 | * the number of inserted text
120 | */
121 | public void processInsert(CharSequence s, int start, int count) {
122 | CharSequence sub = s.subSequence(start, start + count);
123 |
124 | if (mCurrentChange != null)
125 | pushCurrentChange();
126 |
127 | mCurrentChange = new TextChangeInsert(sub, start);
128 | }
129 |
130 | /**
131 | * @param s
132 | * the sequence being modified
133 | * @param start
134 | * the first character index
135 | * @param count
136 | * the number of inserted text
137 | */
138 | public void processDelete(CharSequence s, int start, int count) {
139 | CharSequence sub = s.subSequence(start, start + count);
140 |
141 | if (mCurrentChange != null)
142 | pushCurrentChange();
143 |
144 | mCurrentChange = new TextChangeDelete(sub, start);
145 | }
146 |
147 | /**
148 | * Pushes the current change on top of the stack
149 | */
150 | protected void pushCurrentChange() {
151 | if (mCurrentChange == null)
152 | return;
153 |
154 | mChanges.push(mCurrentChange);
155 | while (mChanges.size() > Settings.UNDO_MAX_STACK) {
156 | mChanges.remove(0);
157 | }
158 | mCurrentChange = null;
159 | }
160 |
161 | /**
162 | * Prints the current stack
163 | */
164 | public void printStack() {
165 | if (!BuildConfig.DEBUG)
166 | return;
167 | Log.i(TAG, "STACK");
168 | for (TextChange change : mChanges) {
169 | Log.d(TAG, change.toString());
170 | }
171 | Log.d(TAG, "Current change : " + mCurrentChange.toString());
172 | }
173 |
174 | protected TextChange mCurrentChange;
175 | protected final Stack mChanges;
176 |
177 | }
178 |
--------------------------------------------------------------------------------
/Ted/res/xml/ted_prefs.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
12 |
17 |
18 |
23 |
29 |
30 |
33 |
34 |
35 |
36 |
42 |
48 |
54 |
55 |
60 |
67 |
68 |
69 |
73 |
74 |
80 |
81 |
85 |
86 |
87 |
91 |
95 |
96 |
97 |
102 |
107 |
108 |
109 |
110 |
--------------------------------------------------------------------------------
/Ted/src/fr/xgouchet/texteditor/common/Settings.java:
--------------------------------------------------------------------------------
1 | package fr.xgouchet.texteditor.common;
2 |
3 | import java.io.File;
4 |
5 | import android.content.Context;
6 | import android.content.SharedPreferences;
7 | import android.content.SharedPreferences.Editor;
8 | import android.graphics.Typeface;
9 |
10 | public class Settings implements Constants {
11 |
12 | /** Number of recent files to remember */
13 | public static int MAX_RECENT_FILES = 10;
14 |
15 | /** Show the lines numbers */
16 | public static boolean SHOW_LINE_NUMBERS = true;
17 | /** automatic break line to fit one page */
18 | public static boolean WORDWRAP = false;
19 | /** color setting */
20 | public static int COLOR = COLOR_CLASSIC;
21 |
22 | /** when search reaches the end of a file, search wrap */
23 | public static boolean SEARCHWRAP = false;
24 | /** only search for matchin case */
25 | public static boolean SEARCHMATCHCASE = false;
26 |
27 | /** Text size setting */
28 | public static int TEXT_SIZE = 12;
29 |
30 | /** Default end of line */
31 | public static int DEFAULT_END_OF_LINE = EOL_LINUX;
32 | /** End Of Line style */
33 | public static int END_OF_LINE = EOL_LINUX;
34 | /** Encoding */
35 | public static String ENCODING = ENC_UTF8;
36 |
37 | /** Let auto save on quit be triggered */
38 | public static boolean FORCE_AUTO_SAVE = false;
39 | public static boolean AUTO_SAVE_OVERWRITE = false;
40 |
41 | /** enable fling to scroll */
42 | public static boolean FLING_TO_SCROLL = false;
43 |
44 | /** Use Undo instead of quit ? */
45 | public static boolean UNDO = true;
46 | /** Undo stack capacity */
47 | public static int UNDO_MAX_STACK = 25;
48 | /** Use back button as undo */
49 | public static boolean BACK_BTN_AS_UNDO = false;
50 |
51 | /** Use a Home Page */
52 | public static boolean USE_HOME_PAGE = false;
53 | /** Home Page Path */
54 | public static String HOME_PAGE_PATH = "";
55 |
56 | /**
57 | * @return the end of line characters according to the current settings
58 | */
59 | public static String getEndOfLine() {
60 | switch (END_OF_LINE) {
61 | case EOL_MAC: // Mac OS
62 | return "\r";
63 | case EOL_WINDOWS: // Windows
64 | return "\r\n";
65 | case EOL_LINUX: // Linux / Android
66 | default:
67 | return "\n";
68 | }
69 | }
70 |
71 | /**
72 | * Update the settings from the given {@link SharedPreferences}
73 | *
74 | * @param settings
75 | * the settings to read from
76 | */
77 | public static void updateFromPreferences(SharedPreferences settings) {
78 |
79 | MAX_RECENT_FILES = getStringPreferenceAsInteger(settings,
80 | PREFERENCE_MAX_RECENTS, "10");
81 | SHOW_LINE_NUMBERS = settings.getBoolean(PREFERENCE_SHOW_LINE_NUMBERS,
82 | true);
83 | WORDWRAP = settings.getBoolean(PREFERENCE_WORDWRAP, false);
84 | TEXT_SIZE = getStringPreferenceAsInteger(settings,
85 | PREFERENCE_TEXT_SIZE, "12");
86 | DEFAULT_END_OF_LINE = getStringPreferenceAsInteger(settings,
87 | PREFERENCE_END_OF_LINES, ("" + EOL_LINUX));
88 | FORCE_AUTO_SAVE = settings.getBoolean(PREFERENCE_AUTO_SAVE, false);
89 | AUTO_SAVE_OVERWRITE = settings.getBoolean(
90 | PREFERENCE_AUTO_SAVE_OVERWRITE, false);
91 | COLOR = getStringPreferenceAsInteger(settings, PREFERENCE_COLOR_THEME,
92 | ("" + COLOR_CLASSIC));
93 | SEARCHWRAP = settings.getBoolean(PREFERENCE_SEARCHWRAP, false);
94 | SEARCHMATCHCASE = settings.getBoolean(PREFERENCE_SEARCH_MATCH_CASE,
95 | false);
96 | ENCODING = settings.getString(PREFERENCE_ENCODING, ENC_UTF8);
97 | FLING_TO_SCROLL = settings.getBoolean(PREFERENCE_FLING_TO_SCROLL, true);
98 |
99 | BACK_BTN_AS_UNDO = settings.getBoolean(PREFERENCE_BACK_BUTTON_AS_UNDO,
100 | false);
101 | UNDO = settings.getBoolean(PREFERENCE_ALLOW_UNDO, true);
102 | UNDO_MAX_STACK = getStringPreferenceAsInteger(settings,
103 | PREFERENCE_MAX_UNDO_STACK, "25");
104 |
105 | USE_HOME_PAGE = settings.getBoolean(PREFERENCE_USE_HOME_PAGE, false);
106 | HOME_PAGE_PATH = settings.getString(PREFERENCE_HOME_PAGE_PATH, "");
107 |
108 | RecentFiles.loadRecentFiles(settings.getString(PREFERENCE_RECENTS, ""));
109 | }
110 |
111 | /**
112 | * Reads a preference stored as a string and returns the numeric value
113 | *
114 | * @param prefs
115 | * the prefernce to read from
116 | * @param key
117 | * the key
118 | * @param def
119 | * the default value
120 | * @return the value as an int
121 | */
122 | protected static int getStringPreferenceAsInteger(SharedPreferences prefs,
123 | String key, String def) {
124 | String strVal;
125 | int intVal;
126 |
127 | strVal = null;
128 | try {
129 | strVal = prefs.getString(key, def);
130 | } catch (Exception e) {
131 | strVal = def;
132 | }
133 |
134 | try {
135 | intVal = Integer.parseInt(strVal);
136 | } catch (NumberFormatException e) {
137 | intVal = 0;
138 | }
139 |
140 | return intVal;
141 | }
142 |
143 | /**
144 | * Save the Home page settings
145 | *
146 | * @param settings
147 | * the settings to write to
148 | */
149 | public static void saveHomePage(SharedPreferences settings) {
150 | Editor editor = settings.edit();
151 | editor.putString(PREFERENCE_HOME_PAGE_PATH, HOME_PAGE_PATH);
152 | editor.commit();
153 |
154 | }
155 |
156 | public static File getFontFile(Context ctx) {
157 | return new File(ctx.getDir(FONT_FOLDER_NAME, Context.MODE_PRIVATE),
158 | FONT_FILE_NAME);
159 | }
160 |
161 | public static Typeface getTypeface(Context ctx) {
162 | File fontFile = getFontFile(ctx);
163 | Typeface res = Typeface.MONOSPACE;
164 | if (fontFile.exists() && fontFile.canRead()) {
165 | res = Typeface.createFromFile(getFontFile(ctx));
166 | }
167 | return res;
168 | }
169 | }
170 |
--------------------------------------------------------------------------------
/Ted/src/fr/xgouchet/texteditor/common/TextFileUtils.java:
--------------------------------------------------------------------------------
1 | package fr.xgouchet.texteditor.common;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.BufferedWriter;
5 | import java.io.File;
6 | import java.io.FileInputStream;
7 | import java.io.FileNotFoundException;
8 | import java.io.FileOutputStream;
9 | import java.io.IOException;
10 | import java.io.InputStreamReader;
11 | import java.io.OutputStreamWriter;
12 |
13 | import fr.xgouchet.texteditor.BuildConfig;
14 | import org.mozilla.universalchardet.UniversalDetector;
15 |
16 | import android.content.Context;
17 | import android.util.Log;
18 |
19 | /**
20 | * Misc file utilities
21 | *
22 | * TODO code review
23 | *
24 | */
25 | public class TextFileUtils implements Constants {
26 |
27 | /**
28 | * @param path
29 | * the absolute path to the file to save
30 | * @param text
31 | * the text to write
32 | * @return if the file was saved successfully
33 | */
34 | public static boolean writeTextFile(String path, String text) {
35 | File file = new File(path);
36 | OutputStreamWriter writer;
37 | FileOutputStream stream;
38 | BufferedWriter out;
39 | String eol_text = text;
40 | try {
41 | if (Settings.END_OF_LINE != EOL_LINUX) {
42 | eol_text = eol_text.replaceAll("\n", Settings.getEndOfLine());
43 | }
44 |
45 | stream = new FileOutputStream(file);
46 | writer = new OutputStreamWriter(stream, Settings.ENCODING);
47 | out = new BufferedWriter(writer);
48 | out.write(eol_text);
49 | out.flush();
50 | stream.getFD().sync();
51 | out.close();
52 | } catch (OutOfMemoryError e) {
53 | Log.w(TAG, "Out of memory error", e);
54 | return false;
55 | } catch (IOException e) {
56 | Log.w(TAG, "Can't write to file " + path, e);
57 | return false;
58 | }
59 | return true;
60 | }
61 |
62 | /**
63 | * @param file
64 | * the file to read
65 | * @return the content of the file as text
66 | */
67 | public static String readTextFile(File file) {
68 | InputStreamReader reader;
69 | BufferedReader in;
70 | StringBuffer text = new StringBuffer();
71 | int c;
72 | try {
73 | reader = new InputStreamReader(new FileInputStream(file),
74 | detectCharSet(file.getAbsolutePath()));
75 | in = new BufferedReader(reader);
76 | do {
77 | c = in.read();
78 | if (c != -1) {
79 | text.append((char) c);
80 | }
81 | } while (c != -1);
82 | in.close();
83 | } catch (IOException e) {
84 | Log.w(TAG, "Can't read file " + file.getName(), e);
85 | return null;
86 | } catch (OutOfMemoryError e) {
87 | Log.w(TAG, "File is to big to read", e);
88 | return null;
89 | }
90 |
91 | // detect end of lines
92 | String content = text.toString();
93 | int windows = content.indexOf("\r\n");
94 | int macos = content.indexOf("\r");
95 |
96 | if (windows != -1) {
97 | Settings.END_OF_LINE = EOL_WINDOWS;
98 | content = content.replaceAll("\r\n", "\n");
99 | } else {
100 | if (macos != -1) {
101 | Settings.END_OF_LINE = EOL_MAC;
102 | content = content.replaceAll("\r", "\n");
103 | } else {
104 | Settings.END_OF_LINE = EOL_LINUX;
105 | }
106 | }
107 |
108 | if (BuildConfig.DEBUG) {
109 | Log.d(TAG, "Using End of Line : " + Settings.END_OF_LINE);
110 | }
111 | return content;
112 | }
113 |
114 | /**
115 | * @param context
116 | * the current context
117 | * @param text
118 | * the text to write
119 | * @return if the file was saved successfully
120 | */
121 | public static boolean writeInternal(Context context, String text) {
122 | FileOutputStream fos;
123 | try {
124 | fos = context
125 | .openFileOutput(BACKUP_FILE_NAME, Context.MODE_PRIVATE);
126 | fos.write(text.getBytes());
127 | fos.close();
128 | if (BuildConfig.DEBUG) {
129 | Log.i(TAG, "Saved to file " + context.getFilesDir().getPath()
130 | + File.separator + BACKUP_FILE_NAME);
131 | }
132 | } catch (FileNotFoundException e) {
133 | Log.w(TAG, "Couldn't write to internal storage ", e);
134 | return false;
135 | } catch (IOException e) {
136 | Log.w(TAG, "Error occured while writing to internal storage ", e);
137 | return false;
138 | }
139 | return true;
140 | }
141 |
142 | /**
143 | * @param context
144 | * the current context
145 | * @return the content of the file as text
146 | */
147 | public static String readInternal(Context context) {
148 | FileInputStream fis;
149 | StringBuffer text = new StringBuffer();
150 |
151 | try {
152 | fis = context.openFileInput(BACKUP_FILE_NAME);
153 | while (fis.available() > 0) {
154 | text.append((char) fis.read());
155 | }
156 | } catch (FileNotFoundException e) {
157 | Log.w(TAG, "No backup file available", e);
158 | return null;
159 | } catch (IOException e) {
160 | Log.w(TAG, "Can't read backup file ", e);
161 | return null;
162 | }
163 | return text.toString();
164 | }
165 |
166 | /**
167 | * @param context
168 | * the current context
169 | */
170 | public static void clearInternal(Context context) {
171 | writeInternal(context, "");
172 | }
173 |
174 | /**
175 | * Detect charset
176 | * @see https://code.google.com/p/juniversalchardet/
177 | * @param fileName
178 | * the absolute path of the file to open
179 | * @return charset name
180 | *
181 | * */
182 | public static String detectCharSet(String fileName) throws IOException {
183 | byte[] buf = new byte[4096];
184 | FileInputStream fis = new FileInputStream(fileName);
185 |
186 | UniversalDetector detector = new UniversalDetector(null);
187 |
188 | int nread;
189 | while ((nread = fis.read(buf)) > 0 && !detector.isDone()) {
190 | detector.handleData(buf, 0, nread);
191 | }
192 | detector.dataEnd();
193 |
194 | String encoding = detector.getDetectedCharset();
195 |
196 | detector.reset();
197 | return encoding;
198 | }
199 | }
200 |
--------------------------------------------------------------------------------
/Ted/src/fr/xgouchet/texteditor/TedSettingsActivity.java:
--------------------------------------------------------------------------------
1 | package fr.xgouchet.texteditor;
2 |
3 | import java.io.File;
4 |
5 | import android.content.ActivityNotFoundException;
6 | import android.content.Context;
7 | import android.content.Intent;
8 | import android.content.SharedPreferences;
9 | import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
10 | import android.os.Bundle;
11 | import android.preference.CheckBoxPreference;
12 | import android.preference.ListPreference;
13 | import android.preference.Preference;
14 | import android.preference.Preference.OnPreferenceClickListener;
15 | import android.preference.PreferenceActivity;
16 | import android.util.Log;
17 | import de.neofonie.mobile.app.android.widget.crouton.Crouton;
18 | import de.neofonie.mobile.app.android.widget.crouton.Style;
19 | import fr.xgouchet.androidlib.data.FileUtils;
20 | import fr.xgouchet.texteditor.common.Constants;
21 | import fr.xgouchet.texteditor.common.Settings;
22 | import fr.xgouchet.texteditor.ui.view.AdvancedEditText;
23 |
24 | @SuppressWarnings("deprecation")
25 | public class TedSettingsActivity extends PreferenceActivity implements
26 | Constants, OnSharedPreferenceChangeListener {
27 |
28 | /**
29 | * @see android.preference.PreferenceActivity#onCreate(android.os.Bundle)
30 | */
31 |
32 | protected void onCreate(Bundle icicle) {
33 | super.onCreate(icicle);
34 |
35 | getPreferenceManager().setSharedPreferencesName(PREFERENCES_NAME);
36 |
37 | addPreferencesFromResource(R.xml.ted_prefs);
38 | setContentView(R.layout.layout_prefs);
39 |
40 | getPreferenceManager().getSharedPreferences()
41 | .registerOnSharedPreferenceChangeListener(this);
42 |
43 | mSampleTED = (AdvancedEditText) findViewById(R.id.sampleEditor);
44 |
45 | Settings.updateFromPreferences(getPreferenceManager()
46 | .getSharedPreferences());
47 | mSampleTED.updateFromSettings();
48 | mSampleTED.setEnabled(false);
49 |
50 | mPreviousHP = Settings.USE_HOME_PAGE;
51 |
52 | findPreference(PREFERENCE_SELECT_FONT).setOnPreferenceClickListener(
53 | new OnPreferenceClickListener() {
54 | public boolean onPreferenceClick(Preference preference) {
55 | Intent selectFont = new Intent();
56 | selectFont.setClass(getApplicationContext(),
57 | TedFontActivity.class);
58 | try {
59 | startActivityForResult(selectFont, REQUEST_FONT);
60 | } catch (ActivityNotFoundException e) {
61 | Crouton.showText(TedSettingsActivity.this,
62 | R.string.toast_activity_open, Style.ALERT);
63 | }
64 | return true;
65 | }
66 | });
67 |
68 | updateSummaries();
69 | }
70 |
71 | /**
72 | * @see android.content.SharedPreferences.OnSharedPreferenceChangeListener#onSharedPreferenceChanged(android.content.SharedPreferences,
73 | * java.lang.String)
74 | */
75 | public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
76 | String key) {
77 | Settings.updateFromPreferences(sharedPreferences);
78 | mSampleTED.updateFromSettings();
79 | updateSummaries();
80 |
81 | CheckBoxPreference checkBox = (CheckBoxPreference) findPreference(PREFERENCE_USE_HOME_PAGE);
82 | checkBox.setSummaryOn(Settings.HOME_PAGE_PATH);
83 |
84 | if (Settings.USE_HOME_PAGE && !mPreviousHP) {
85 | Intent setHomePage = new Intent();
86 | setHomePage.setClass(this, TedOpenActivity.class);
87 | setHomePage.putExtra(EXTRA_REQUEST_CODE, REQUEST_HOME_PAGE);
88 | try {
89 | startActivityForResult(setHomePage, REQUEST_HOME_PAGE);
90 | } catch (ActivityNotFoundException e) {
91 | Crouton.showText(this, R.string.toast_activity_open,
92 | Style.ALERT);
93 | }
94 | }
95 |
96 | mPreviousHP = Settings.USE_HOME_PAGE;
97 | }
98 |
99 | /**
100 | * @see android.preference.PreferenceActivity#onActivityResult(int, int,
101 | * android.content.Intent)
102 | */
103 | protected void onActivityResult(int requestCode, int resultCode, Intent data) {
104 | Bundle extras;
105 |
106 | if (BuildConfig.DEBUG)
107 | Log.d(TAG, "onActivityResult");
108 |
109 | if (resultCode == RESULT_CANCELED) {
110 | if (BuildConfig.DEBUG)
111 | Log.d(TAG, "Result canceled");
112 | ((CheckBoxPreference) findPreference(PREFERENCE_USE_HOME_PAGE))
113 | .setChecked(false);
114 | return;
115 | }
116 |
117 | if ((resultCode != RESULT_OK) || (data == null)) {
118 | if (BuildConfig.DEBUG)
119 | Log.e(TAG, "Result error or null data! / " + resultCode);
120 | ((CheckBoxPreference) findPreference(PREFERENCE_USE_HOME_PAGE))
121 | .setChecked(false);
122 | return;
123 | }
124 |
125 | switch (requestCode) {
126 | case REQUEST_HOME_PAGE:
127 | extras = data.getExtras();
128 | if (extras != null) {
129 | if (BuildConfig.DEBUG)
130 | Log.d(TAG, "Open : " + extras.getString("path"));
131 | Settings.HOME_PAGE_PATH = extras.getString("path");
132 | Settings.saveHomePage(getSharedPreferences(PREFERENCES_NAME,
133 | Context.MODE_PRIVATE));
134 | updateSummaries();
135 | }
136 | break;
137 | case REQUEST_FONT:
138 | Log.i(TAG, "Selected Font : " + data.getData().getPath());
139 | File src = new File(data.getData().getPath());
140 | FileUtils.copyFile(src, Settings.getFontFile(this));
141 | mSampleTED.updateFromSettings();
142 | break;
143 | }
144 | }
145 |
146 | /**
147 | * Updates the summaries for every list
148 | */
149 | protected void updateSummaries() {
150 | ListPreference listPref;
151 | CheckBoxPreference cbPref;
152 |
153 | listPref = (ListPreference) findPreference(PREFERENCE_COLOR_THEME);
154 | listPref.setSummary(listPref.getEntry());
155 |
156 | listPref = (ListPreference) findPreference(PREFERENCE_TEXT_SIZE);
157 | listPref.setSummary(listPref.getEntry());
158 |
159 | listPref = (ListPreference) findPreference(PREFERENCE_END_OF_LINES);
160 | listPref.setSummary(listPref.getEntry());
161 |
162 | listPref = (ListPreference) findPreference(PREFERENCE_ENCODING);
163 | listPref.setSummary(listPref.getEntry());
164 |
165 | listPref = (ListPreference) findPreference(PREFERENCE_MAX_RECENTS);
166 | listPref.setSummary(listPref.getEntry());
167 |
168 | listPref = (ListPreference) findPreference(PREFERENCE_MAX_UNDO_STACK);
169 | listPref.setSummary(listPref.getEntry());
170 |
171 | cbPref = (CheckBoxPreference) findPreference(PREFERENCE_USE_HOME_PAGE);
172 | if (cbPref.isChecked()) {
173 | cbPref.setSummaryOn(Settings.HOME_PAGE_PATH);
174 | }
175 | }
176 |
177 | protected AdvancedEditText mSampleTED;
178 | protected boolean mPreviousHP;
179 |
180 | }
181 |
--------------------------------------------------------------------------------
/Ted/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
11 |
12 |
16 |
17 |
18 |
19 |
20 |
21 |
24 |
25 |
26 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
62 |
66 |
70 |
74 |
78 |
82 |
86 |
90 |
94 |
98 |
102 |
103 |
104 |
105 |
106 |
110 |
111 |
112 |
113 |
117 |
118 |
119 |
120 |
123 |
124 |
125 |
126 |
130 |
131 |
132 |
133 |
137 |
138 |
139 |
140 |
144 |
145 |
146 |
147 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
160 |
161 |
162 |
163 |
164 |
167 |
168 |
169 |
170 |
--------------------------------------------------------------------------------
/Ted/src/fr/xgouchet/texteditor/common/Constants.java:
--------------------------------------------------------------------------------
1 | package fr.xgouchet.texteditor.common;
2 |
3 | import java.io.File;
4 |
5 | import android.os.Environment;
6 |
7 | /**
8 | * @author x.gouchet
9 | *
10 | */
11 | public interface Constants {
12 |
13 | /** Tag for the log ( = {@value} ) */
14 | public static final String TAG = "TED";
15 |
16 | public static final String ACTION_WIDGET_OPEN = "fr.xgouchet.texteditor.ACTION_TED_WIDGET_OPEN";
17 |
18 | /** Fonts folder */
19 | public static final String FONT_FOLDER_NAME = "fonts";
20 | /** Font file */
21 | public static final String FONT_FILE_NAME = "ted_font.ttf";
22 |
23 | /** clears the current text ( = {@value} ) */
24 | public static final int MENU_ID_NEW = 0;
25 | /** Saves the file ( = {@value} ) */
26 | public static final int MENU_ID_SAVE = 1;
27 | /** Savesas a new file ( = {@value} ) */
28 | public static final int MENU_ID_SAVE_AS = 2;
29 | /** open an existing file */
30 | public static final int MENU_ID_OPEN = 3;
31 | /** open an existing file ( = {@value} ) */
32 | public static final int MENU_ID_OPEN_RECENT = 4;
33 | /** open the settings ( = {@value} ) */
34 | public static final int MENU_ID_SETTINGS = 5;
35 | /** open the about page ( = {@value} ) */
36 | public static final int MENU_ID_ABOUT = 6;
37 | /** Search a string in the file ( = {@value} ) */
38 | public static final int MENU_ID_SEARCH = 7;
39 | /** undo last change ( = {@value} ) */
40 | public static final int MENU_ID_UNDO = 8;
41 | /** redo last change ( = {@value} ) */
42 | public static final int MENU_ID_REDO = 9;
43 | /** Quit the app ( = {@value} ) */
44 | public static final int MENU_ID_QUIT = 666;
45 |
46 | /** File of the external storage data */
47 | public static final File STORAGE = Environment
48 | .getExternalStorageDirectory();
49 | /** Path to the external storage data */
50 | public static final String STORAGE_PATH = STORAGE.getAbsolutePath();
51 | /** name of the backup file */
52 | public static final String BACKUP_FILE_NAME = "temp.bak";
53 |
54 | /** name of the shared preferences for this app ( = {@value} ) */
55 | public static final String PREFERENCES_NAME = "fr.xgouchet.texteditor";
56 | /** Preference tag to retrieve the recent files ( = {@value} ) */
57 | public static final String PREFERENCE_RECENTS = "recent_files";
58 | /** Preference tag to retrieve the recent files ( = {@value} ) */
59 | public static final String PREFERENCE_MAX_RECENTS = "max_recent_files";
60 | /** Preference tag to retrieve the show line number ( = {@value} ) */
61 | public static final String PREFERENCE_SHOW_LINE_NUMBERS = "show_line_numbers";
62 | /** Preference tag to retrieve the wordwrap ( = {@value} ) */
63 | public static final String PREFERENCE_WORDWRAP = "auto_break_lines";
64 | /** Preference tag to retrieve the searchwrap ( = {@value} ) */
65 | public static final String PREFERENCE_SEARCHWRAP = "search_wrap";
66 | /** Preference tag to retrieve the search match case ( = {@value} ) */
67 | public static final String PREFERENCE_SEARCH_MATCH_CASE = "search_match_case";
68 | /** Preference tag to retrieve the Syntax Highlight ( = {@value} ) */
69 | public static final String PREFERENCE_HIGHLIGHT = "highlight_syntax";
70 | /** Preference tag to retrieve the Text Size ( = {@value} ) */
71 | public static final String PREFERENCE_TEXT_SIZE = "text_size";
72 | /** Preference tag to retrieve the End of lines pref ( = {@value} ) */
73 | public static final String PREFERENCE_END_OF_LINES = "end_of_lines";
74 | /** Preference tag to retrieve the Encoding pref ( = {@value} ) */
75 | public static final String PREFERENCE_ENCODING = "encoding";
76 | /** Preference tag to retrieve the Auto mode ( = {@value} ) */
77 | public static final String PREFERENCE_AUTO_SAVE = "force_auto_save";
78 | /** Preference tag to retrieve the Auto mode ( = {@value} ) */
79 | public static final String PREFERENCE_AUTO_SAVE_OVERWRITE = "auto_save_overwrite";
80 | /** Preference tag to retrieve the Color Theme ( = {@value} ) */
81 | public static final String PREFERENCE_COLOR_THEME = "color_theme";
82 | /** Preference tag to retrieve the fling to scroll ( = {@value} ) */
83 | public static final String PREFERENCE_FLING_TO_SCROLL = "fling_to_scroll";
84 | /** Preference tag to retrieve if undo history is allowed ( = {@value} ) */
85 | public static final String PREFERENCE_ALLOW_UNDO = "allow_undo";
86 | /** Preference tag to retrieve the max undo stack ( = {@value} ) */
87 | public static final String PREFERENCE_MAX_UNDO_STACK = "max_undo_stack";
88 | /** Preference tag to retrieve the back button as undo ( = {@value} ) */
89 | public static final String PREFERENCE_BACK_BUTTON_AS_UNDO = "back_button_as_undo";
90 | /** Preference tag to retrieve the use home page ( = {@value} ) */
91 | public static final String PREFERENCE_USE_HOME_PAGE = "use_home_page";
92 | /** Preference tag to retrieve the home page path ( = {@value} ) */
93 | public static final String PREFERENCE_HOME_PAGE_PATH = "home_page_path";
94 | /** Preference tag to select the font ( = {@value} ) */
95 | public static final String PREFERENCE_SELECT_FONT = "select_font";
96 | /** Preference tag to the text font ( = {@value} ) */
97 | public static final String PREFERENCE_FONT = "text_font";
98 |
99 | /** minimum text size */
100 | public static final int TEXT_SIZE_MIN = 9;
101 | /** maximum text size */
102 | public static final int TEXT_SIZE_MAX = 40;
103 |
104 | /** End of line setting for Linux files ( = {@value} ) */
105 | public static final int EOL_LINUX = 0;
106 | /** End of line setting for Windows files ( = {@value} ) */
107 | public static final int EOL_WINDOWS = 1;
108 | /** End of line setting for Mac files ( = {@value} ) */
109 | public static final int EOL_MAC = 2;
110 |
111 | /** Encoding : 7 bit ASCII ( = {@value} ) */
112 | public static final String ENC_ASCII = "US-ASCII";
113 | /** Encoding : ISO Latin Alphabet, aka ISO-LATIN-1 ( = {@value} ) */
114 | public static final String ENC_LATIN = "ISO-8859-1";
115 | /** Encoding : 8 bit UCS Transformation Format ( = {@value} ) */
116 | public static final String ENC_UTF8 = "UTF-8";
117 |
118 | /** color theme default : black on white ( = {@value} ) */
119 | public static final int COLOR_CLASSIC = 0;
120 | /** color theme negative : white on black ( = {@value} ) */
121 | public static final int COLOR_NEGATIVE = 1;
122 | /** color theme matrix : green on dark green ( = {@value} ) */
123 | public static final int COLOR_MATRIX = 2;
124 | /** color theme sky : darkblue on skyblue ( = {@value} ) */
125 | public static final int COLOR_SKY = 3;
126 | /** color theme dracula : red on black ( = {@value} ) */
127 | public static final int COLOR_DRACULA = 4;
128 |
129 | /** Request code for Save As Activity */
130 | public static final int REQUEST_SAVE_AS = 107;
131 | /** Request code for Open Activity */
132 | public static final int REQUEST_OPEN = 108;
133 | /** Request code for Home Page Activity */
134 | public static final int REQUEST_HOME_PAGE = 109;
135 | /** Request code for Font Activity */
136 | public static final int REQUEST_FONT = 110;
137 |
138 | /** extra when browsing for file */
139 | public static final String EXTRA_REQUEST_CODE = "request_code";
140 | /** Extra to force read only from widget */
141 | public static final String EXTRA_FORCE_READ_ONLY = "force_read_only";
142 |
143 | /** an error result */
144 | public static final int RESULT_ERROR = 1;
145 | }
146 |
--------------------------------------------------------------------------------
/Ted/res/layout/layout_about.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
12 |
13 |
14 |
15 |
21 |
22 |
27 |
28 |
33 |
34 |
39 |
40 |
45 |
46 |
51 |
52 |
57 |
58 |
63 |
64 |
69 |
70 |
75 |
76 |
81 |
82 |
87 |
88 |
93 |
94 |
99 |
100 |
105 |
106 |
111 |
112 |
117 |
118 |
123 |
124 |
129 |
130 |
135 |
136 |
141 |
142 |
147 |
148 |
153 |
154 |
159 |
160 |
165 |
166 |
171 |
172 |
177 |
178 |
183 |
184 |
189 |
190 |
195 |
196 |
201 |
202 |
207 |
208 |
213 |
214 |
215 |
--------------------------------------------------------------------------------
/Ted/src/fr/xgouchet/texteditor/ui/view/AdvancedEditText.java:
--------------------------------------------------------------------------------
1 | package fr.xgouchet.texteditor.ui.view;
2 |
3 | import android.content.Context;
4 | import android.graphics.Canvas;
5 | import android.graphics.Color;
6 | import android.graphics.Paint;
7 | import android.graphics.Point;
8 | import android.graphics.Rect;
9 | import android.graphics.Typeface;
10 | import android.util.AttributeSet;
11 | import android.view.GestureDetector;
12 | import android.view.GestureDetector.OnGestureListener;
13 | import android.view.KeyEvent;
14 | import android.view.MotionEvent;
15 | import android.view.View;
16 | import android.view.View.OnKeyListener;
17 | import android.view.inputmethod.InputMethodManager;
18 | import android.widget.EditText;
19 | import android.widget.Scroller;
20 | import fr.xgouchet.texteditor.R;
21 | import fr.xgouchet.texteditor.common.Constants;
22 | import fr.xgouchet.texteditor.common.Settings;
23 |
24 | /**
25 | * TODO create a syntax highlighter
26 | */
27 | public class AdvancedEditText extends EditText implements Constants,
28 | OnKeyListener, OnGestureListener {
29 |
30 | /**
31 | * @param context
32 | * the current context
33 | * @param attrs
34 | * some attributes
35 | * @category ObjectLifecycle
36 | */
37 | public AdvancedEditText(Context context, AttributeSet attrs) {
38 | super(context, attrs);
39 |
40 | mPaintNumbers = new Paint();
41 | mPaintNumbers.setTypeface(Typeface.MONOSPACE);
42 | mPaintNumbers.setAntiAlias(true);
43 |
44 | mPaintHighlight = new Paint();
45 |
46 | mScale = context.getResources().getDisplayMetrics().density;
47 | mPadding = (int) (mPaddingDP * mScale);
48 |
49 | mHighlightedLine = mHighlightStart = -1;
50 |
51 | mDrawingRect = new Rect();
52 | mLineBounds = new Rect();
53 |
54 | mGestureDetector = new GestureDetector(getContext(), this);
55 |
56 | updateFromSettings();
57 | }
58 |
59 | /**
60 | * @see android.widget.TextView#computeScroll()
61 | * @category View
62 | */
63 | public void computeScroll() {
64 |
65 | if (mTedScroller != null) {
66 | if (mTedScroller.computeScrollOffset()) {
67 | scrollTo(mTedScroller.getCurrX(), mTedScroller.getCurrY());
68 | }
69 | } else {
70 | super.computeScroll();
71 | }
72 | }
73 |
74 | /**
75 | * @see EditText#onDraw(Canvas)
76 | * @category View
77 | */
78 | public void onDraw(Canvas canvas) {
79 | int count, lineX, baseline;
80 |
81 | count = getLineCount();
82 |
83 | if (Settings.SHOW_LINE_NUMBERS) {
84 | int padding = (int) (Math.floor(Math.log10(count)) + 1);
85 | padding = (int) ((padding * mPaintNumbers.getTextSize()) + mPadding + (Settings.TEXT_SIZE
86 | * mScale * 0.5));
87 | if (mLinePadding != padding) {
88 | mLinePadding = padding;
89 | setPadding(mLinePadding, mPadding, mPadding, mPadding);
90 | }
91 | }
92 |
93 | // get the drawing boundaries
94 | getDrawingRect(mDrawingRect);
95 |
96 | // display current line
97 | computeLineHighlight();
98 |
99 | // draw line numbers
100 | lineX = (int) (mDrawingRect.left + mLinePadding - (Settings.TEXT_SIZE
101 | * mScale * 0.5));
102 | int min = 0;
103 | int max = count;
104 | getLineBounds(0, mLineBounds);
105 | int startBottom = mLineBounds.bottom;
106 | int startTop = mLineBounds.top;
107 | getLineBounds(count - 1, mLineBounds);
108 | int endBottom = mLineBounds.bottom;
109 | int endTop = mLineBounds.top;
110 | if (count > 1 && endBottom > startBottom && endTop > startTop) {
111 | min = Math.max(min, ((mDrawingRect.top - startBottom) * (count - 1)) / (endBottom - startBottom));
112 | max = Math.min(max, ((mDrawingRect.bottom - startTop) * (count - 1)) / (endTop - startTop) + 1);
113 | }
114 | for (int i = min; i < max; i++) {
115 | baseline = getLineBounds(i, mLineBounds);
116 | if ((mMaxSize != null) && (mMaxSize.x < mLineBounds.right)) {
117 | mMaxSize.x = mLineBounds.right;
118 | }
119 |
120 | if ((i == mHighlightedLine) && (!Settings.WORDWRAP)) {
121 | canvas.drawRect(mLineBounds, mPaintHighlight);
122 | }
123 |
124 | if (Settings.SHOW_LINE_NUMBERS) {
125 | canvas.drawText("" + (i + 1), mDrawingRect.left + mPadding,
126 | baseline, mPaintNumbers);
127 | }
128 | if (Settings.SHOW_LINE_NUMBERS) {
129 | canvas.drawLine(lineX, mDrawingRect.top, lineX,
130 | mDrawingRect.bottom, mPaintNumbers);
131 | }
132 | }
133 | getLineBounds(count - 1, mLineBounds);
134 | if (mMaxSize != null) {
135 | mMaxSize.y = mLineBounds.bottom;
136 | mMaxSize.x = Math.max(mMaxSize.x + mPadding - mDrawingRect.width(),
137 | 0);
138 | mMaxSize.y = Math.max(
139 | mMaxSize.y + mPadding - mDrawingRect.height(), 0);
140 | }
141 |
142 | super.onDraw(canvas);
143 | }
144 |
145 | /**
146 | * @see android.view.View.OnKeyListener#onKey(android.view.View, int,
147 | * android.view.KeyEvent)
148 | */
149 | public boolean onKey(View v, int keyCode, KeyEvent event) {
150 | return false;
151 | }
152 |
153 | /**
154 | * @see android.widget.TextView#onTouchEvent(android.view.MotionEvent)
155 | * @category GestureDetection
156 | */
157 | public boolean onTouchEvent(MotionEvent event) {
158 |
159 | super.onTouchEvent(event);
160 | if (mGestureDetector != null) {
161 | return mGestureDetector.onTouchEvent(event);
162 | }
163 |
164 | return true;
165 | }
166 |
167 | /**
168 | * @see android.view.GestureDetector.OnGestureListener#onDown(android.view.MotionEvent)
169 | * @category GestureDetection
170 | */
171 | public boolean onDown(MotionEvent e) {
172 | return true;
173 | }
174 |
175 | /**
176 | * @see android.view.GestureDetector.OnGestureListener#onSingleTapUp(android.view.MotionEvent)
177 | * @category GestureDetection
178 | */
179 | public boolean onSingleTapUp(MotionEvent e) {
180 | if (isEnabled()) {
181 | ((InputMethodManager) getContext().getSystemService(
182 | Context.INPUT_METHOD_SERVICE)).showSoftInput(this,
183 | InputMethodManager.SHOW_IMPLICIT);
184 | }
185 | return true;
186 | }
187 |
188 | /**
189 | * @see android.view.GestureDetector.OnGestureListener#onShowPress(android.view.MotionEvent)
190 | * @category GestureDetection
191 | */
192 | public void onShowPress(MotionEvent e) {
193 | }
194 |
195 | /**
196 | * @see android.view.GestureDetector.OnGestureListener#onLongPress(android.view.MotionEvent)
197 | */
198 | public void onLongPress(MotionEvent e) {
199 |
200 | }
201 |
202 | /**
203 | * @see android.view.GestureDetector.OnGestureListener#onScroll(android.view.MotionEvent,
204 | * android.view.MotionEvent, float, float)
205 | */
206 | public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
207 | float distanceY) {
208 | // mTedScroller.setFriction(0);
209 | return true;
210 | }
211 |
212 | /**
213 | * @see android.view.GestureDetector.OnGestureListener#onFling(android.view.MotionEvent,
214 | * android.view.MotionEvent, float, float)
215 | */
216 | public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
217 | float velocityY) {
218 | if (!Settings.FLING_TO_SCROLL) {
219 | return true;
220 | }
221 |
222 | if (mTedScroller != null) {
223 | mTedScroller.fling(getScrollX(), getScrollY(), -(int) velocityX,
224 | -(int) velocityY, 0, mMaxSize.x, 0, mMaxSize.y);
225 | }
226 | return true;
227 | }
228 |
229 | /**
230 | * Update view settings from the app preferences
231 | *
232 | * @category Custom
233 | */
234 | public void updateFromSettings() {
235 |
236 | if (isInEditMode()) {
237 | return;
238 | }
239 |
240 | setTypeface(Settings.getTypeface(getContext()));
241 |
242 | // wordwrap
243 | setHorizontallyScrolling(!Settings.WORDWRAP);
244 |
245 | // color Theme
246 | switch (Settings.COLOR) {
247 | case COLOR_NEGATIVE:
248 | setBackgroundResource(R.drawable.textfield_black);
249 | setTextColor(Color.WHITE);
250 | mPaintHighlight.setColor(Color.WHITE);
251 | mPaintNumbers.setColor(Color.GRAY);
252 | break;
253 | case COLOR_MATRIX:
254 | setBackgroundResource(R.drawable.textfield_matrix);
255 | setTextColor(Color.GREEN);
256 | mPaintHighlight.setColor(Color.GREEN);
257 | mPaintNumbers.setColor(Color.rgb(0, 128, 0));
258 | break;
259 | case COLOR_SKY:
260 | setBackgroundResource(R.drawable.textfield_sky);
261 | setTextColor(Color.rgb(0, 0, 64));
262 | mPaintHighlight.setColor(Color.rgb(0, 0, 64));
263 | mPaintNumbers.setColor(Color.rgb(0, 128, 255));
264 | break;
265 | case COLOR_DRACULA:
266 | setBackgroundResource(R.drawable.textfield_dracula);
267 | setTextColor(Color.RED);
268 | mPaintHighlight.setColor(Color.RED);
269 | mPaintNumbers.setColor(Color.rgb(192, 0, 0));
270 | break;
271 | case COLOR_CLASSIC:
272 | default:
273 | setBackgroundResource(R.drawable.textfield_white);
274 | setTextColor(Color.BLACK);
275 | mPaintHighlight.setColor(Color.BLACK);
276 | mPaintNumbers.setColor(Color.GRAY);
277 | break;
278 | }
279 | mPaintHighlight.setAlpha(48);
280 |
281 | // text size
282 | setTextSize(Settings.TEXT_SIZE);
283 | mPaintNumbers.setTextSize(Settings.TEXT_SIZE * mScale * 0.85f);
284 |
285 | // refresh view
286 | postInvalidate();
287 | refreshDrawableState();
288 |
289 | // use Fling when scrolling settings ?
290 | if (Settings.FLING_TO_SCROLL) {
291 | mTedScroller = new Scroller(getContext());
292 | mMaxSize = new Point();
293 | } else {
294 | mTedScroller = null;
295 | mMaxSize = null;
296 | }
297 |
298 | // padding
299 | mLinePadding = mPadding;
300 | int count = getLineCount();
301 | if (Settings.SHOW_LINE_NUMBERS) {
302 | mLinePadding = (int) (Math.floor(Math.log10(count)) + 1);
303 | mLinePadding = (int) ((mLinePadding * mPaintNumbers.getTextSize())
304 | + mPadding + (Settings.TEXT_SIZE * mScale * 0.5));
305 | setPadding(mLinePadding, mPadding, mPadding, mPadding);
306 | } else {
307 | setPadding(mPadding, mPadding, mPadding, mPadding);
308 | }
309 | }
310 |
311 | /**
312 | * Compute the line to highlight based on selection
313 | */
314 | protected void computeLineHighlight() {
315 | int i, line, selStart;
316 | String text;
317 |
318 | if (!isEnabled()) {
319 | mHighlightedLine = -1;
320 | return;
321 | }
322 |
323 | selStart = getSelectionStart();
324 | if (mHighlightStart != selStart) {
325 | text = getText().toString();
326 |
327 | line = i = 0;
328 | while (i < selStart) {
329 | i = text.indexOf("\n", i);
330 | if (i < 0) {
331 | break;
332 | }
333 | if (i < selStart) {
334 | ++line;
335 | }
336 | ++i;
337 | }
338 |
339 | mHighlightedLine = line;
340 | }
341 | }
342 |
343 | /** The line numbers paint */
344 | protected Paint mPaintNumbers;
345 | /** The line numbers paint */
346 | protected Paint mPaintHighlight;
347 | /** the offset value in dp */
348 | protected int mPaddingDP = 6;
349 | /** the padding scaled */
350 | protected int mPadding, mLinePadding;
351 | /** the scale for desnity pixels */
352 | protected float mScale;
353 |
354 | /** the scroller instance */
355 | protected Scroller mTedScroller;
356 | /** the velocity tracker */
357 | protected GestureDetector mGestureDetector;
358 | /** the Max size of the view */
359 | protected Point mMaxSize;
360 |
361 | /** the highlighted line index */
362 | protected int mHighlightedLine;
363 | protected int mHighlightStart;
364 |
365 | protected Rect mDrawingRect, mLineBounds;
366 | }
367 |
--------------------------------------------------------------------------------
/Ted/src/fr/xgouchet/texteditor/TedActivity.java:
--------------------------------------------------------------------------------
1 | package fr.xgouchet.texteditor;
2 |
3 | import static fr.xgouchet.androidlib.data.FileUtils.deleteItem;
4 | import static fr.xgouchet.androidlib.data.FileUtils.getCanonizePath;
5 | import static fr.xgouchet.androidlib.data.FileUtils.renameItem;
6 | import static fr.xgouchet.androidlib.ui.Toaster.showToast;
7 | import static fr.xgouchet.androidlib.ui.activity.ActivityDecorator.addMenuItem;
8 | import static fr.xgouchet.androidlib.ui.activity.ActivityDecorator.showMenuItemAsAction;
9 |
10 | import java.io.File;
11 | import java.net.URI;
12 | import java.net.URISyntaxException;
13 |
14 | import android.annotation.TargetApi;
15 | import android.app.Activity;
16 | import android.app.AlertDialog.Builder;
17 | import android.content.ActivityNotFoundException;
18 | import android.content.Context;
19 | import android.content.DialogInterface;
20 | import android.content.Intent;
21 | import android.content.SharedPreferences;
22 | import android.content.res.Configuration;
23 | import android.os.Build.VERSION;
24 | import android.os.Build.VERSION_CODES;
25 | import android.os.Bundle;
26 | import android.text.Editable;
27 | import android.text.TextUtils;
28 | import android.text.TextWatcher;
29 | import android.util.Log;
30 | import android.view.KeyEvent;
31 | import android.view.Menu;
32 | import android.view.MenuItem;
33 | import android.view.View;
34 | import android.view.View.OnClickListener;
35 | import android.widget.EditText;
36 | import de.neofonie.mobile.app.android.widget.crouton.Crouton;
37 | import de.neofonie.mobile.app.android.widget.crouton.Style;
38 | import fr.xgouchet.texteditor.common.Constants;
39 | import fr.xgouchet.texteditor.common.RecentFiles;
40 | import fr.xgouchet.texteditor.common.Settings;
41 | import fr.xgouchet.texteditor.common.TedChangelog;
42 | import fr.xgouchet.texteditor.common.TextFileUtils;
43 | import fr.xgouchet.texteditor.ui.view.AdvancedEditText;
44 | import fr.xgouchet.texteditor.undo.TextChangeWatcher;
45 |
46 | public class TedActivity extends Activity implements Constants, TextWatcher,
47 | OnClickListener {
48 |
49 | /**
50 | * @see android.app.Activity#onCreate(android.os.Bundle)
51 | */
52 | protected void onCreate(Bundle savedInstanceState) {
53 | super.onCreate(savedInstanceState);
54 | if (BuildConfig.DEBUG)
55 | Log.d(TAG, "onCreate");
56 |
57 | setContentView(R.layout.layout_editor);
58 |
59 | Settings.updateFromPreferences(getSharedPreferences(PREFERENCES_NAME,
60 | MODE_PRIVATE));
61 |
62 | //
63 | mReadIntent = true;
64 |
65 | // editor
66 | mEditor = (AdvancedEditText) findViewById(R.id.editor);
67 | mEditor.addTextChangedListener(this);
68 | mEditor.updateFromSettings();
69 | mWatcher = new TextChangeWatcher();
70 | mWarnedShouldQuit = false;
71 | mDoNotBackup = false;
72 |
73 | // search
74 | mSearchLayout = findViewById(R.id.searchLayout);
75 | mSearchInput = (EditText) findViewById(R.id.textSearch);
76 | findViewById(R.id.buttonSearchClose).setOnClickListener(this);
77 | findViewById(R.id.buttonSearchNext).setOnClickListener(this);
78 | findViewById(R.id.buttonSearchPrev).setOnClickListener(this);
79 | }
80 |
81 | /**
82 | * @see android.app.Activity#onStart()
83 | */
84 | protected void onStart() {
85 | super.onStart();
86 |
87 | TedChangelog changeLog;
88 | SharedPreferences prefs;
89 |
90 | changeLog = new TedChangelog();
91 | prefs = getSharedPreferences(Constants.PREFERENCES_NAME,
92 | Context.MODE_PRIVATE);
93 |
94 | if (changeLog.isFirstLaunchAfterUpdate(this, prefs)) {
95 | Builder builder = new Builder(this);
96 | String message = getString(changeLog.getTitleResource(this))
97 | + "\n\n" + getString(changeLog.getChangeLogResource(this));
98 | builder.setTitle(R.string.ui_whats_new);
99 | builder.setMessage(message);
100 | builder.setCancelable(true);
101 | builder.setPositiveButton(android.R.string.ok,
102 | new DialogInterface.OnClickListener() {
103 | public void onClick(DialogInterface dialog, int which) {
104 | dialog.dismiss();
105 | }
106 | });
107 |
108 | builder.create().show();
109 | }
110 |
111 | changeLog.saveCurrentVersion(this, prefs);
112 | }
113 |
114 | /**
115 | * @see android.app.Activity#onRestart()
116 | */
117 | protected void onRestart() {
118 | super.onRestart();
119 | mReadIntent = false;
120 | }
121 |
122 | /**
123 | * @see android.app.Activity#onRestoreInstanceState(android.os.Bundle)
124 | */
125 | protected void onRestoreInstanceState(Bundle savedInstanceState) {
126 | super.onRestoreInstanceState(savedInstanceState);
127 | Log.d("TED", "onRestoreInstanceState");
128 | Log.v("TED", mEditor.getText().toString());
129 | }
130 |
131 | /**
132 | * @see android.app.Activity#onResume()
133 | */
134 | protected void onResume() {
135 | super.onResume();
136 | if (BuildConfig.DEBUG)
137 | Log.d(TAG, "onResume");
138 |
139 | if (mReadIntent) {
140 | readIntent();
141 | }
142 |
143 | mReadIntent = false;
144 |
145 | updateTitle();
146 | mEditor.updateFromSettings();
147 | }
148 |
149 | /**
150 | * @see android.app.Activity#onPause()
151 | */
152 | protected void onPause() {
153 | super.onPause();
154 | if (BuildConfig.DEBUG)
155 | Log.d(TAG, "onPause");
156 |
157 | if (Settings.FORCE_AUTO_SAVE && mDirty && (!mReadOnly)) {
158 | if ((mCurrentFilePath == null) || (mCurrentFilePath.length() == 0))
159 | doAutoSaveFile();
160 | else if (Settings.AUTO_SAVE_OVERWRITE)
161 | doSaveFile(mCurrentFilePath);
162 | }
163 | }
164 |
165 | /**
166 | * @see android.app.Activity#onActivityResult(int, int,
167 | * android.content.Intent)
168 | *
169 | */
170 | @TargetApi(11)
171 | protected void onActivityResult(int requestCode, int resultCode, Intent data) {
172 | Bundle extras;
173 | if (BuildConfig.DEBUG)
174 | Log.d(TAG, "onActivityResult");
175 | mReadIntent = false;
176 |
177 | if (resultCode == RESULT_CANCELED) {
178 | if (BuildConfig.DEBUG)
179 | Log.d(TAG, "Result canceled");
180 | return;
181 | }
182 |
183 | if ((resultCode != RESULT_OK) || (data == null)) {
184 | if (BuildConfig.DEBUG)
185 | Log.e(TAG, "Result error or null data! / " + resultCode);
186 | return;
187 | }
188 |
189 | extras = data.getExtras();
190 | if (extras == null) {
191 | if (BuildConfig.DEBUG)
192 | Log.e(TAG, "No extra data ! ");
193 | return;
194 | }
195 |
196 | switch (requestCode) {
197 | case REQUEST_SAVE_AS:
198 | if (BuildConfig.DEBUG)
199 | Log.d(TAG, "Save as : " + extras.getString("path"));
200 | doSaveFile(extras.getString("path"));
201 | break;
202 | case REQUEST_OPEN:
203 | if (BuildConfig.DEBUG)
204 | Log.d(TAG, "Open : " + extras.getString("path"));
205 | doOpenFile(new File(extras.getString("path")), false);
206 | break;
207 | }
208 | }
209 |
210 | /**
211 | * @see android.app.Activity#onConfigurationChanged(android.content.res.Configuration)
212 | */
213 | public void onConfigurationChanged(Configuration newConfig) {
214 | super.onConfigurationChanged(newConfig);
215 | if (BuildConfig.DEBUG)
216 | Log.d(TAG, "onConfigurationChanged");
217 | }
218 |
219 | /**
220 | * @see android.app.Activity#onCreateOptionsMenu(android.view.Menu)
221 | */
222 | public boolean onCreateOptionsMenu(Menu menu) {
223 | super.onCreateOptionsMenu(menu);
224 |
225 | return true;
226 | }
227 |
228 | /**
229 | * @see android.app.Activity#onPrepareOptionsMenu(android.view.Menu)
230 | */
231 | @TargetApi(11)
232 | public boolean onPrepareOptionsMenu(Menu menu) {
233 | super.onPrepareOptionsMenu(menu);
234 |
235 | menu.clear();
236 |
237 | addMenuItem(menu, MENU_ID_NEW, R.string.menu_new,
238 | R.drawable.ic_menu_file_new);
239 | addMenuItem(menu, MENU_ID_OPEN, R.string.menu_open,
240 | R.drawable.ic_menu_file_open);
241 |
242 | if (!mReadOnly)
243 | addMenuItem(menu, MENU_ID_SAVE, R.string.menu_save,
244 | R.drawable.ic_menu_save);
245 |
246 | if ((!mReadOnly) && Settings.UNDO)
247 | addMenuItem(menu, MENU_ID_UNDO, R.string.menu_undo,
248 | R.drawable.ic_menu_undo);
249 |
250 | addMenuItem(menu, MENU_ID_SEARCH, R.string.menu_search,
251 | R.drawable.ic_menu_search);
252 |
253 | if (RecentFiles.getRecentFiles().size() > 0)
254 | addMenuItem(menu, MENU_ID_OPEN_RECENT, R.string.menu_open_recent,
255 | R.drawable.ic_menu_recent);
256 |
257 | addMenuItem(menu, MENU_ID_SAVE_AS, R.string.menu_save_as, 0);
258 |
259 | addMenuItem(menu, MENU_ID_SETTINGS, R.string.menu_settings, 0);
260 |
261 | addMenuItem(menu, MENU_ID_ABOUT, R.string.menu_about, 0);
262 |
263 | if (Settings.BACK_BTN_AS_UNDO && Settings.UNDO)
264 | addMenuItem(menu, MENU_ID_QUIT, R.string.menu_quit, 0);
265 |
266 | if ((!mReadOnly) && Settings.UNDO)
267 | showMenuItemAsAction(menu.findItem(MENU_ID_UNDO),
268 | R.drawable.ic_menu_undo);
269 | showMenuItemAsAction(menu.findItem(MENU_ID_SEARCH),
270 | R.drawable.ic_menu_search);
271 |
272 | return true;
273 | }
274 |
275 | /**
276 | * @see android.app.Activity#onOptionsItemSelected(android.view.MenuItem)
277 | */
278 | public boolean onOptionsItemSelected(MenuItem item) {
279 | mWarnedShouldQuit = false;
280 | switch (item.getItemId()) {
281 | case MENU_ID_NEW:
282 | newContent();
283 | return true;
284 | case MENU_ID_SAVE:
285 | saveContent();
286 | break;
287 | case MENU_ID_SAVE_AS:
288 | saveContentAs();
289 | break;
290 | case MENU_ID_OPEN:
291 | openFile();
292 | break;
293 | case MENU_ID_OPEN_RECENT:
294 | openRecentFile();
295 | break;
296 | case MENU_ID_SEARCH:
297 | search();
298 | break;
299 | case MENU_ID_SETTINGS:
300 | settingsActivity();
301 | return true;
302 | case MENU_ID_ABOUT:
303 | aboutActivity();
304 | return true;
305 | case MENU_ID_QUIT:
306 | quit();
307 | return true;
308 | case MENU_ID_UNDO:
309 | if (!undo()) {
310 | Crouton.showText(this, R.string.toast_warn_no_undo, Style.INFO);
311 | }
312 | return true;
313 | }
314 | return super.onOptionsItemSelected(item);
315 | }
316 |
317 | /**
318 | * @see android.text.TextWatcher#beforeTextChanged(java.lang.CharSequence,
319 | * int, int, int)
320 | */
321 | public void beforeTextChanged(CharSequence s, int start, int count,
322 | int after) {
323 | if (Settings.UNDO && (!mInUndo) && (mWatcher != null))
324 | mWatcher.beforeChange(s, start, count, after);
325 | }
326 |
327 | /**
328 | * @see android.text.TextWatcher#onTextChanged(java.lang.CharSequence, int,
329 | * int, int)
330 | */
331 | public void onTextChanged(CharSequence s, int start, int before, int count) {
332 | if (mInUndo)
333 | return;
334 |
335 | if (Settings.UNDO && (!mInUndo) && (mWatcher != null))
336 | mWatcher.afterChange(s, start, before, count);
337 |
338 | }
339 |
340 | /**
341 | * @see android.text.TextWatcher#afterTextChanged(android.text.Editable)
342 | */
343 | public void afterTextChanged(Editable s) {
344 | if (!mDirty) {
345 | mDirty = true;
346 | updateTitle();
347 | }
348 | }
349 |
350 | /**
351 | * @see android.app.Activity#onKeyUp(int, android.view.KeyEvent)
352 | */
353 | public boolean onKeyUp(int keyCode, KeyEvent event) {
354 | switch (keyCode) {
355 | case KeyEvent.KEYCODE_BACK:
356 | if (mSearchLayout.getVisibility() != View.GONE)
357 | search();
358 | else if (Settings.UNDO && Settings.BACK_BTN_AS_UNDO) {
359 | if (!undo())
360 | warnOrQuit();
361 | } else
362 | quit();
363 | return true;
364 | case KeyEvent.KEYCODE_SEARCH:
365 | search();
366 | mWarnedShouldQuit = false;
367 | return true;
368 | }
369 | mWarnedShouldQuit = false;
370 | return super.onKeyUp(keyCode, event);
371 | }
372 |
373 | /**
374 | * @see OnClickListener#onClick(View)
375 | */
376 | public void onClick(View v) {
377 | mWarnedShouldQuit = false;
378 | switch (v.getId()) {
379 | case R.id.buttonSearchClose:
380 | search();
381 | break;
382 | case R.id.buttonSearchNext:
383 | searchNext();
384 | break;
385 | case R.id.buttonSearchPrev:
386 | searchPrevious();
387 | break;
388 | }
389 | }
390 |
391 | /**
392 | * Read the intent used to start this activity (open the text file) as well
393 | * as the non configuration instance if activity is started after a screen
394 | * rotate
395 | */
396 | protected void readIntent() {
397 | Intent intent;
398 | String action;
399 | File file;
400 |
401 | intent = getIntent();
402 | if (intent == null) {
403 | if (BuildConfig.DEBUG)
404 | Log.d(TAG, "No intent found, use default instead");
405 | doDefaultAction();
406 | return;
407 | }
408 |
409 | action = intent.getAction();
410 | if (action == null) {
411 | if (BuildConfig.DEBUG)
412 | Log.d(TAG, "Intent w/o action, default action");
413 | doDefaultAction();
414 | } else if ((action.equals(Intent.ACTION_VIEW))
415 | || (action.equals(Intent.ACTION_EDIT))) {
416 | try {
417 | file = new File(new URI(intent.getData().toString()));
418 | doOpenFile(file, false);
419 | } catch (URISyntaxException e) {
420 | Crouton.showText(this, R.string.toast_intent_invalid_uri,
421 | Style.ALERT);
422 | } catch (IllegalArgumentException e) {
423 | Crouton.showText(this, R.string.toast_intent_illegal,
424 | Style.ALERT);
425 | }
426 | } else if (action.equals(ACTION_WIDGET_OPEN)) {
427 | try {
428 | file = new File(new URI(intent.getData().toString()));
429 | doOpenFile(file,
430 | intent.getBooleanExtra(EXTRA_FORCE_READ_ONLY, false));
431 | } catch (URISyntaxException e) {
432 | Crouton.showText(this, R.string.toast_intent_invalid_uri,
433 | Style.ALERT);
434 | } catch (IllegalArgumentException e) {
435 | Crouton.showText(this, R.string.toast_intent_illegal,
436 | Style.ALERT);
437 | }
438 | } else {
439 | doDefaultAction();
440 | }
441 | }
442 |
443 | /**
444 | * Run the default startup action
445 | */
446 | protected void doDefaultAction() {
447 | File file;
448 | boolean loaded;
449 | loaded = false;
450 |
451 | if (doOpenBackup())
452 | loaded = true;
453 |
454 | if ((!loaded) && Settings.USE_HOME_PAGE) {
455 | file = new File(Settings.HOME_PAGE_PATH);
456 | if ((file == null) || (!file.exists())) {
457 | Crouton.showText(this, R.string.toast_open_home_page_error,
458 | Style.ALERT);
459 | } else if (!file.canRead()) {
460 | Crouton.showText(this, R.string.toast_home_page_cant_read,
461 | Style.ALERT);
462 | } else {
463 | loaded = doOpenFile(file, false);
464 | }
465 | }
466 |
467 | if (!loaded)
468 | doClearContents();
469 | }
470 |
471 | /**
472 | * Clears the content of the editor. Assumes that user was prompted and
473 | * previous data was saved
474 | */
475 | protected void doClearContents() {
476 | mWatcher = null;
477 | mInUndo = true;
478 | mEditor.setText("");
479 | mCurrentFilePath = null;
480 | mCurrentFileName = null;
481 | Settings.END_OF_LINE = Settings.DEFAULT_END_OF_LINE;
482 | mDirty = false;
483 | mReadOnly = false;
484 | mWarnedShouldQuit = false;
485 | mWatcher = new TextChangeWatcher();
486 | mInUndo = false;
487 | mDoNotBackup = false;
488 |
489 | TextFileUtils.clearInternal(getApplicationContext());
490 |
491 | updateTitle();
492 | }
493 |
494 | /**
495 | * Opens the given file and replace the editors content with the file.
496 | * Assumes that user was prompted and previous data was saved
497 | *
498 | * @param file
499 | * the file to load
500 | * @param forceReadOnly
501 | * force the file to be used as read only
502 | * @return if the file was loaded successfully
503 | */
504 | protected boolean doOpenFile(File file, boolean forceReadOnly) {
505 | String text;
506 |
507 | if (file == null)
508 | return false;
509 |
510 | if (BuildConfig.DEBUG)
511 | Log.i(TAG, "Openning file " + file.getName());
512 |
513 | try {
514 | text = TextFileUtils.readTextFile(file);
515 | if (text != null) {
516 | mInUndo = true;
517 | mEditor.setText(text);
518 | mWatcher = new TextChangeWatcher();
519 | mCurrentFilePath = getCanonizePath(file);
520 | mCurrentFileName = file.getName();
521 | RecentFiles.updateRecentList(mCurrentFilePath);
522 | RecentFiles.saveRecentList(getSharedPreferences(
523 | PREFERENCES_NAME, MODE_PRIVATE));
524 | mDirty = false;
525 | mInUndo = false;
526 | mDoNotBackup = false;
527 | if (file.canWrite() && (!forceReadOnly)) {
528 | mReadOnly = false;
529 | mEditor.setEnabled(true);
530 | } else {
531 | mReadOnly = true;
532 | mEditor.setEnabled(false);
533 | }
534 |
535 | updateTitle();
536 |
537 | return true;
538 | } else {
539 | Crouton.showText(this, R.string.toast_open_error, Style.ALERT);
540 | }
541 | } catch (OutOfMemoryError e) {
542 | Crouton.showText(this, R.string.toast_memory_open, Style.ALERT);
543 | }
544 |
545 | return false;
546 | }
547 |
548 | /**
549 | * Open the last backup file
550 | *
551 | * @return if a backup file was loaded
552 | */
553 | protected boolean doOpenBackup() {
554 |
555 | String text;
556 |
557 | try {
558 | text = TextFileUtils.readInternal(this);
559 | if (!TextUtils.isEmpty(text)) {
560 | mInUndo = true;
561 | mEditor.setText(text);
562 | mWatcher = new TextChangeWatcher();
563 | mCurrentFilePath = null;
564 | mCurrentFileName = null;
565 | mDirty = false;
566 | mInUndo = false;
567 | mDoNotBackup = false;
568 | mReadOnly = false;
569 | mEditor.setEnabled(true);
570 |
571 | updateTitle();
572 |
573 | return true;
574 | } else {
575 | return false;
576 | }
577 | } catch (OutOfMemoryError e) {
578 | Crouton.showText(this, R.string.toast_memory_open, Style.ALERT);
579 | }
580 |
581 | return true;
582 | }
583 |
584 | /**
585 | * Saves the text editor's content into a file at the given path. If an
586 | * after save {@link Runnable} exists, run it
587 | *
588 | * @param path
589 | * the path to the file (must be a valid path and not null)
590 | */
591 | protected void doSaveFile(String path) {
592 | String content;
593 |
594 | if (path == null) {
595 | Crouton.showText(this, R.string.toast_save_null, Style.ALERT);
596 | return;
597 | }
598 |
599 | content = mEditor.getText().toString();
600 |
601 | if (!TextFileUtils.writeTextFile(path + ".tmp", content)) {
602 | Crouton.showText(this, R.string.toast_save_temp, Style.ALERT);
603 | return;
604 | }
605 |
606 | if (!deleteItem(path)) {
607 | Crouton.showText(this, R.string.toast_save_delete, Style.ALERT);
608 | return;
609 | }
610 |
611 | if (!renameItem(path + ".tmp", path)) {
612 | Crouton.showText(this, R.string.toast_save_rename, Style.ALERT);
613 | return;
614 | }
615 |
616 | mCurrentFilePath = getCanonizePath(new File(path));
617 | mCurrentFileName = (new File(path)).getName();
618 | RecentFiles.updateRecentList(path);
619 | RecentFiles.saveRecentList(getSharedPreferences(PREFERENCES_NAME,
620 | MODE_PRIVATE));
621 | mReadOnly = false;
622 | mDirty = false;
623 | updateTitle();
624 | Crouton.showText(this, R.string.toast_save_success, Style.CONFIRM);
625 |
626 | runAfterSave();
627 | }
628 |
629 | protected void doAutoSaveFile() {
630 | if (mDoNotBackup) {
631 | doClearContents();
632 | }
633 |
634 | String text = mEditor.getText().toString();
635 | if (text.length() == 0)
636 | return;
637 |
638 | if (TextFileUtils.writeInternal(this, text)) {
639 | showToast(this, R.string.toast_file_saved_auto, false);
640 | }
641 | }
642 |
643 | /**
644 | * Undo the last change
645 | *
646 | * @return if an undo was don
647 | */
648 | protected boolean undo() {
649 | boolean didUndo = false;
650 | mInUndo = true;
651 | int caret;
652 | caret = mWatcher.undo(mEditor.getText());
653 | if (caret >= 0) {
654 | mEditor.setSelection(caret, caret);
655 | didUndo = true;
656 | }
657 | mInUndo = false;
658 |
659 | return didUndo;
660 | }
661 |
662 | /**
663 | * Prompt the user to save the current file before doing something else
664 | */
665 | protected void promptSaveDirty() {
666 | Builder builder;
667 |
668 | if (!mDirty) {
669 | runAfterSave();
670 | return;
671 | }
672 |
673 | builder = new Builder(this);
674 | builder.setTitle(R.string.app_name);
675 | builder.setMessage(R.string.ui_save_text);
676 |
677 | builder.setPositiveButton(R.string.ui_save,
678 | new DialogInterface.OnClickListener() {
679 | public void onClick(DialogInterface dialog, int which) {
680 | saveContent();
681 | mDoNotBackup = true;
682 | }
683 | });
684 | builder.setNegativeButton(R.string.ui_cancel,
685 | new DialogInterface.OnClickListener() {
686 | public void onClick(DialogInterface dialog, int which) {
687 |
688 | }
689 | });
690 | builder.setNeutralButton(R.string.ui_no_save,
691 | new DialogInterface.OnClickListener() {
692 | public void onClick(DialogInterface dialog, int which) {
693 | runAfterSave();
694 | mDoNotBackup = true;
695 | }
696 | });
697 |
698 | builder.create().show();
699 |
700 | }
701 |
702 | /**
703 | *
704 | */
705 | protected void newContent() {
706 | mAfterSave = new Runnable() {
707 | public void run() {
708 | doClearContents();
709 | }
710 | };
711 |
712 | promptSaveDirty();
713 | }
714 |
715 | /**
716 | * Runs the after save to complete
717 | */
718 | protected void runAfterSave() {
719 | if (mAfterSave == null) {
720 | if (BuildConfig.DEBUG)
721 | Log.d(TAG, "No After shave, ignoring...");
722 | return;
723 | }
724 |
725 | mAfterSave.run();
726 |
727 | mAfterSave = null;
728 | }
729 |
730 | /**
731 | * Starts an activity to choose a file to open
732 | */
733 | protected void openFile() {
734 | if (BuildConfig.DEBUG)
735 | Log.d(TAG, "openFile");
736 |
737 | mAfterSave = new Runnable() {
738 | public void run() {
739 | Intent open = new Intent();
740 | open.setClass(getApplicationContext(), TedOpenActivity.class);
741 | // open = new Intent(ACTION_OPEN);
742 | open.putExtra(EXTRA_REQUEST_CODE, REQUEST_OPEN);
743 | try {
744 | startActivityForResult(open, REQUEST_OPEN);
745 | } catch (ActivityNotFoundException e) {
746 | Crouton.showText(TedActivity.this,
747 | R.string.toast_activity_open, Style.ALERT);
748 | }
749 | }
750 | };
751 |
752 | promptSaveDirty();
753 | }
754 |
755 | /**
756 | * Open the recent files activity to open
757 | */
758 | protected void openRecentFile() {
759 | if (BuildConfig.DEBUG)
760 | Log.d(TAG, "openRecentFile");
761 |
762 | if (RecentFiles.getRecentFiles().size() == 0) {
763 | Crouton.showText(this, R.string.toast_no_recent_files, Style.ALERT);
764 | return;
765 | }
766 |
767 | mAfterSave = new Runnable() {
768 | public void run() {
769 | Intent open;
770 |
771 | open = new Intent();
772 | open.setClass(TedActivity.this, TedOpenRecentActivity.class);
773 | try {
774 | startActivityForResult(open, REQUEST_OPEN);
775 | } catch (ActivityNotFoundException e) {
776 | Crouton.showText(TedActivity.this,
777 | R.string.toast_activity_open_recent, Style.ALERT);
778 | }
779 | }
780 | };
781 |
782 | promptSaveDirty();
783 | }
784 |
785 | /**
786 | * Warns the user that the next back press will qui the application, or quit
787 | * if the warning has already been shown
788 | */
789 | protected void warnOrQuit() {
790 | if (mWarnedShouldQuit) {
791 | quit();
792 | } else {
793 | Crouton.showText(this, R.string.toast_warn_no_undo_will_quit,
794 | Style.INFO);
795 | mWarnedShouldQuit = true;
796 | }
797 | }
798 |
799 | /**
800 | * Quit the app (user pressed back)
801 | */
802 | protected void quit() {
803 | mAfterSave = new Runnable() {
804 | public void run() {
805 | finish();
806 | }
807 | };
808 |
809 | promptSaveDirty();
810 | }
811 |
812 | /**
813 | * General save command : check if a path exist for the current content,
814 | * then save it , else invoke the {@link TedActivity#saveContentAs()} method
815 | */
816 | protected void saveContent() {
817 | if ((mCurrentFilePath == null) || (mCurrentFilePath.length() == 0)) {
818 | saveContentAs();
819 | } else {
820 | doSaveFile(mCurrentFilePath);
821 | }
822 | }
823 |
824 | /**
825 | * General Save as command : prompt the user for a location and file name,
826 | * then save the editor'd content
827 | */
828 | protected void saveContentAs() {
829 | if (BuildConfig.DEBUG)
830 | Log.d(TAG, "saveContentAs");
831 | Intent saveAs;
832 | saveAs = new Intent();
833 | saveAs.setClass(this, TedSaveAsActivity.class);
834 | try {
835 | startActivityForResult(saveAs, REQUEST_SAVE_AS);
836 | } catch (ActivityNotFoundException e) {
837 | Crouton.showText(this, R.string.toast_activity_save_as, Style.ALERT);
838 | }
839 | }
840 |
841 | /**
842 | * Opens / close the search interface
843 | */
844 | protected void search() {
845 | if (BuildConfig.DEBUG)
846 | Log.d(TAG, "search");
847 | switch (mSearchLayout.getVisibility()) {
848 | case View.GONE:
849 | mSearchLayout.setVisibility(View.VISIBLE);
850 | break;
851 | case View.VISIBLE:
852 | default:
853 | mSearchLayout.setVisibility(View.GONE);
854 | break;
855 | }
856 | }
857 |
858 | /**
859 | * Uses the user input to search a file
860 | */
861 | protected void searchNext() {
862 | String search, text;
863 | int selection, next;
864 |
865 | search = mSearchInput.getText().toString();
866 | text = mEditor.getText().toString();
867 | selection = mEditor.getSelectionEnd();
868 |
869 | if (search.length() == 0) {
870 | Crouton.showText(this, R.string.toast_search_no_input, Style.INFO);
871 | return;
872 | }
873 |
874 | if (!Settings.SEARCHMATCHCASE) {
875 | search = search.toLowerCase();
876 | text = text.toLowerCase();
877 | }
878 |
879 | next = text.indexOf(search, selection);
880 |
881 | if (next > -1) {
882 | mEditor.setSelection(next, next + search.length());
883 | if (!mEditor.isFocused())
884 | mEditor.requestFocus();
885 | } else {
886 | if (Settings.SEARCHWRAP) {
887 | next = text.indexOf(search);
888 | if (next > -1) {
889 | mEditor.setSelection(next, next + search.length());
890 | if (!mEditor.isFocused())
891 | mEditor.requestFocus();
892 | } else {
893 | Crouton.showText(this, R.string.toast_search_not_found,
894 | Style.INFO);
895 | }
896 | } else {
897 | Crouton.showText(this, R.string.toast_search_eof, Style.INFO);
898 | }
899 | }
900 | }
901 |
902 | /**
903 | * Uses the user input to search a file
904 | */
905 | protected void searchPrevious() {
906 | String search, text;
907 | int selection, next;
908 |
909 | search = mSearchInput.getText().toString();
910 | text = mEditor.getText().toString();
911 | selection = mEditor.getSelectionStart() - 1;
912 |
913 | if (search.length() == 0) {
914 | Crouton.showText(this, R.string.toast_search_no_input, Style.INFO);
915 | return;
916 | }
917 |
918 | if (!Settings.SEARCHMATCHCASE) {
919 | search = search.toLowerCase();
920 | text = text.toLowerCase();
921 | }
922 |
923 | next = text.lastIndexOf(search, selection);
924 |
925 | if (next > -1) {
926 | mEditor.setSelection(next, next + search.length());
927 | if (!mEditor.isFocused())
928 | mEditor.requestFocus();
929 | } else {
930 | if (Settings.SEARCHWRAP) {
931 | next = text.lastIndexOf(search);
932 | if (next > -1) {
933 | mEditor.setSelection(next, next + search.length());
934 | if (!mEditor.isFocused())
935 | mEditor.requestFocus();
936 | } else {
937 | Crouton.showText(this, R.string.toast_search_not_found,
938 | Style.INFO);
939 | }
940 | } else {
941 | Crouton.showText(this, R.string.toast_search_eof, Style.INFO);
942 | }
943 | }
944 | }
945 |
946 | /**
947 | * Opens the about activity
948 | */
949 | protected void aboutActivity() {
950 | Intent about = new Intent();
951 | about.setClass(this, TedAboutActivity.class);
952 | try {
953 | startActivity(about);
954 | } catch (ActivityNotFoundException e) {
955 | Crouton.showText(this, R.string.toast_activity_about, Style.ALERT);
956 | }
957 | }
958 |
959 | /**
960 | * Opens the settings activity
961 | */
962 | protected void settingsActivity() {
963 |
964 | mAfterSave = new Runnable() {
965 | public void run() {
966 | Intent settings = new Intent();
967 | settings.setClass(TedActivity.this, TedSettingsActivity.class);
968 | try {
969 | startActivity(settings);
970 | } catch (ActivityNotFoundException e) {
971 | Crouton.showText(TedActivity.this,
972 | R.string.toast_activity_settings, Style.ALERT);
973 | }
974 | }
975 | };
976 |
977 | promptSaveDirty();
978 | }
979 |
980 | /**
981 | * Update the window title
982 | */
983 | @TargetApi(11)
984 | protected void updateTitle() {
985 | String title;
986 | String name;
987 |
988 | name = "?";
989 | if ((mCurrentFileName != null) && (mCurrentFileName.length() > 0))
990 | name = mCurrentFileName;
991 |
992 | if (mReadOnly)
993 | title = getString(R.string.title_editor_readonly, name);
994 | else if (mDirty)
995 | title = getString(R.string.title_editor_dirty, name);
996 | else
997 | title = getString(R.string.title_editor, name);
998 |
999 | setTitle(title);
1000 |
1001 | if (VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB)
1002 | invalidateOptionsMenu();
1003 | }
1004 |
1005 | /** the text editor */
1006 | protected AdvancedEditText mEditor;
1007 | /** the path of the file currently opened */
1008 | protected String mCurrentFilePath;
1009 | /** the name of the file currently opened */
1010 | protected String mCurrentFileName;
1011 | /** the runable to run after a save */
1012 | protected Runnable mAfterSave; // Mennen ? Axe ?
1013 |
1014 | /** is dirty ? */
1015 | protected boolean mDirty;
1016 | /** is read only */
1017 | protected boolean mReadOnly;
1018 |
1019 | /** the search layout root */
1020 | protected View mSearchLayout;
1021 | /** the search input */
1022 | protected EditText mSearchInput;
1023 |
1024 | /** Undo watcher */
1025 | protected TextChangeWatcher mWatcher;
1026 | protected boolean mInUndo;
1027 | protected boolean mWarnedShouldQuit;
1028 | protected boolean mDoNotBackup;
1029 |
1030 | /** are we in a post activity result ? */
1031 | protected boolean mReadIntent;
1032 |
1033 | }
--------------------------------------------------------------------------------