├── app
├── .gitignore
├── src
│ ├── main
│ │ ├── ic_launcher-web.png
│ │ ├── res
│ │ │ ├── mipmap-hdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-mdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── values
│ │ │ │ ├── dimens.xml
│ │ │ │ ├── colors.xml
│ │ │ │ ├── styles.xml
│ │ │ │ └── strings.xml
│ │ │ ├── values-v21
│ │ │ │ └── styles.xml
│ │ │ ├── values-w820dp
│ │ │ │ └── dimens.xml
│ │ │ ├── drawable
│ │ │ │ ├── ic_done_24dp.xml
│ │ │ │ ├── ic_format_italic_24px.xml
│ │ │ │ ├── ic_brush_big_24px.xml
│ │ │ │ ├── ic_delete_24px.xml
│ │ │ │ ├── ic_text_format_24px.xml
│ │ │ │ ├── ic_format_underlined_24px.xml
│ │ │ │ ├── ic_brush_medium_24px.xml
│ │ │ │ ├── ic_brush_small_24px.xml
│ │ │ │ ├── ic_draw_24dp.xml
│ │ │ │ ├── ic_keyboard_voice_24dp.xml
│ │ │ │ ├── ic_format_text_color_24px.xml
│ │ │ │ ├── ic_search_24px.xml
│ │ │ │ ├── ic_format_bold_24px.xml
│ │ │ │ ├── ic_keyboard_24px.xml
│ │ │ │ ├── ic_erase_24px.xml
│ │ │ │ └── ic_brush_color_24dp.xml
│ │ │ ├── menu
│ │ │ │ ├── context_menu_note_select.xml
│ │ │ │ ├── menu_main.xml
│ │ │ │ └── menu_note.xml
│ │ │ ├── layout
│ │ │ │ ├── content_main.xml
│ │ │ │ ├── listview_item_row.xml
│ │ │ │ ├── activity_main.xml
│ │ │ │ ├── activity_note.xml
│ │ │ │ ├── content_text_format.xml
│ │ │ │ └── content_draw_panel.xml
│ │ │ ├── values-ja
│ │ │ │ └── strings.xml
│ │ │ └── values-pl
│ │ │ │ └── strings.xml
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── example
│ │ │ │ └── tomek
│ │ │ │ └── notepad
│ │ │ │ ├── BitmapConverter.java
│ │ │ │ ├── SaveOrUpdateNoteTask.java
│ │ │ │ ├── Note.java
│ │ │ │ ├── NoteAdapter.java
│ │ │ │ ├── DrawingView.java
│ │ │ │ ├── DatabaseHandler.java
│ │ │ │ ├── MainActivity.java
│ │ │ │ └── NoteActivity.java
│ │ └── AndroidManifest.xml
│ └── androidTest
│ │ └── java
│ │ └── com
│ │ └── example
│ │ └── tomek
│ │ └── notepad
│ │ └── DatabaseTestCase.java
├── proguard-rules.pro
└── build.gradle
├── settings.gradle
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── .gitignore
├── gradle.properties
├── README.md
├── gradlew.bat
├── gradlew
└── LICENSE
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------
/app/src/main/ic_launcher-web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tmarzeion/drawable-notepad/HEAD/app/src/main/ic_launcher-web.png
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tmarzeion/drawable-notepad/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tmarzeion/drawable-notepad/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tmarzeion/drawable-notepad/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tmarzeion/drawable-notepad/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tmarzeion/drawable-notepad/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tmarzeion/drawable-notepad/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Mon Apr 23 17:05:13 CEST 2018
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 10dp
4 | 5dp
5 | 16dp
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values-v21/styles.xml:
--------------------------------------------------------------------------------
1 | >
2 |
3 |
9 |
10 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # IDE files
2 | .idea/
3 | *.iml
4 | .classpath
5 | .project
6 | .settings/
7 | import-summary.txt
8 | imports/**/.classpath
9 | imports/**/.project
10 | imports/**/lint.xml
11 |
12 | secure.properties
13 | local.properties
14 | *.class
15 | *.apk
16 | *.ap_
17 | *.dex
18 | bin/
19 | gen/
20 | out/
21 |
22 | *.swp
23 | *.log
24 | .gradle
25 | .DS_store
26 | build/
27 | proguard/
28 |
29 |
--------------------------------------------------------------------------------
/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_done_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_format_italic_24px.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_brush_big_24px.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_delete_24px.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_text_format_24px.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/context_menu_note_select.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_format_underlined_24px.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_brush_medium_24px.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_brush_small_24px.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_draw_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_keyboard_voice_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_format_text_color_24px.xml:
--------------------------------------------------------------------------------
1 |
6 |
10 |
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_search_24px.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_format_bold_24px.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #7990aa
4 | #54748b
5 | #8499b1
6 | #bdcfe4
7 |
8 | #000000
9 | #e8000d
10 | #1c39bb
11 | #32cd32
12 | #e6e200
13 | #EEEEEE
14 |
15 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_keyboard_24px.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_erase_24px.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /home/tomek/Android/Sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_main.xml:
--------------------------------------------------------------------------------
1 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
12 |
13 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_brush_color_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
--------------------------------------------------------------------------------
/app/src/main/java/com/example/tomek/notepad/BitmapConverter.java:
--------------------------------------------------------------------------------
1 | package com.example.tomek.notepad;
2 |
3 | import android.graphics.Bitmap;
4 | import android.graphics.BitmapFactory;
5 |
6 | import java.io.ByteArrayOutputStream;
7 |
8 | public final class BitmapConverter {
9 |
10 | private BitmapConverter() throws InstantiationException {
11 | throw new InstantiationException("This class is not for instantiation");
12 | }
13 |
14 | // convert from bitmap to byte array
15 | public static byte[] getBytes(Bitmap bitmap) {
16 | ByteArrayOutputStream stream = new ByteArrayOutputStream();
17 | bitmap.compress(Bitmap.CompressFormat.PNG, 0, stream);
18 | return stream.toByteArray();
19 | }
20 |
21 | // convert from byte array to bitmap
22 | public static Bitmap getImage(byte[] image) {
23 | return BitmapFactory.decodeByteArray(image, 0, image.length);
24 | }
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/content_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
14 |
15 |
16 |
20 |
21 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
11 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | ext.supportLibraryVersion = '26.1.0'
4 |
5 | repositories {
6 | maven {
7 | url "https://maven.google.com"
8 | }
9 | }
10 |
11 | android {
12 | compileSdkVersion 26
13 | buildToolsVersion '27.0.3'
14 | defaultConfig {
15 | applicationId "com.tomaszmarzeion.notepad"
16 | minSdkVersion 21
17 | targetSdkVersion 26
18 | versionCode 10
19 | versionName "1.22"
20 | testInstrumentationRunner 'android.support.test.runner.AndroidJUnitRunner'
21 | }
22 | lintOptions {
23 | // TODO: Get lint working
24 | abortOnError false
25 | }
26 | buildTypes {
27 | release {
28 | minifyEnabled true
29 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
30 | }
31 | debug {}
32 | }
33 | }
34 |
35 | dependencies {
36 | compile fileTree(include: ['*.jar'], dir: 'libs')
37 |
38 | // Testing
39 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
40 | exclude group: 'com.android.support', module: 'support-annotations'
41 | })
42 | testCompile 'junit:junit:4.12'
43 |
44 | // Support libraries
45 | compile "com.android.support:appcompat-v7:$supportLibraryVersion"
46 | compile "com.android.support:design:$supportLibraryVersion"
47 | compile "com.android.support:support-v4:$supportLibraryVersion"
48 | }
49 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_note.xml:
--------------------------------------------------------------------------------
1 |
41 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/listview_item_row.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
16 |
17 |
27 |
28 |
38 |
39 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
14 |
15 |
21 |
22 |
23 |
24 |
25 |
26 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/tomek/notepad/SaveOrUpdateNoteTask.java:
--------------------------------------------------------------------------------
1 | package com.example.tomek.notepad;
2 |
3 | import android.content.Context;
4 | import android.os.AsyncTask;
5 | import android.widget.Toast;
6 |
7 | import java.util.ArrayList;
8 |
9 | public class SaveOrUpdateNoteTask extends AsyncTask {
10 |
11 | private final Context mCallingActivity;
12 | private final DatabaseHandler mDbHandler;
13 |
14 | public SaveOrUpdateNoteTask(Context context) {
15 | mCallingActivity = context;
16 | mDbHandler = new DatabaseHandler(context);
17 | }
18 |
19 | @Override
20 | protected Boolean doInBackground(Note... params) {
21 |
22 | Note note = params[0];
23 |
24 | // If new note
25 | if (note.getId() == -1) {
26 | mDbHandler.createNote(note);
27 | return true;
28 | } else {
29 | mDbHandler.updateNote(note);
30 | return false;
31 | }
32 | }
33 |
34 | @Override
35 | protected void onPostExecute(Boolean result) {
36 |
37 | boolean createdNewNote = result;
38 |
39 | ArrayList allNotes = mDbHandler.getAllNotesAsArrayList();
40 | if (createdNewNote) {
41 | Toast.makeText(mCallingActivity, mCallingActivity.getString(R.string.toast_note_created), Toast.LENGTH_SHORT).show();
42 | MainActivity.noteAdapter.add(allNotes.get(mDbHandler.getNoteCount() - 1));
43 | } else {
44 | Toast.makeText(mCallingActivity, mCallingActivity.getString(R.string.toast_note_updated), Toast.LENGTH_SHORT).show();
45 | }
46 |
47 | //TODO Get rid of these statics
48 | MainActivity.noteAdapter.setData(allNotes);
49 | MainActivity.noteAdapter.notifyDataSetChanged();
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://dashboard.buddybuild.com/apps/59ceb086a89efa0001364f5f/build/latest?branch=develop)
2 | # Drawable Notepad
3 | [](https://github.com/szafir1100/drawable-notepad)
4 | ## ~~NOTE: Not supported anymore :(~~
5 | ~~27.09.2017 - Lets pimp this project :)~~ - [Reimplementing App in Flutter framework](https://github.com/tmarzeion/flutter-drawable-notepad)
6 |
7 |
8 | Drawable Notepad is lightweight aplication that allows user to write some notes and draw on them.
9 |
10 | ## Get Drawable Notepad
11 |
12 | [](https://play.google.com/store/apps/details?id=com.tomaszmarzeion.notepad&hl=pl)
13 |
14 | ## Screenshots
15 |
16 | [
](http://i.imgur.com/NXh2fAG.png)
17 | [
](http://i.imgur.com/X0Wgi4C.png)
18 | [
](http://i.imgur.com/ebGNBdQ.png)
19 | [
](http://i.imgur.com/y5jEEU3.png)
20 | [
](http://i.imgur.com/xRqI8xf.png)
21 | [
](http://i.imgur.com/ZBCrDNe.png)
22 | [
](http://i.imgur.com/yRnPqpB.png)
23 |
24 | ### Features
25 | - Text format panel
26 | - Drawing panel
27 | - Search notes
28 | - Note titles
29 | - Speech to text function
30 | - Saving notes in SQLite database
31 |
32 | ### Upcoming features
33 | - Filter notes by hashtag
34 | - French, German, Spanish translations
35 | - Photo notes
36 |
37 | Send some more features ideas if You have some!
38 |
39 | ## Contribution
40 | Feel free to improve Drawable Notepad if You have any ideas!
41 | Build is verifed by Travis CI
42 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_note.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
17 |
18 |
23 |
24 |
33 |
34 |
48 |
49 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/app/src/main/res/values-ja/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | メモ帳
3 | メモを追加
4 | メモを削除
5 | 検索
6 | テキストを整形
7 | 完了
8 | キーボードを表示
9 | 音声入力
10 | ここにメモを書いてください…
11 | すべてのメモを削除
12 | テスト
13 | 話してください
14 |
15 | すべて消去
16 | ブラシ
17 | 消しゴム
18 | ペイント
19 | 描画
20 |
21 |
22 | メモを検索…
23 | よろしいですか?
24 | アプリケーションを閉じる
25 | メモ #%d を削除
26 | メモ #%d を削除しました
27 | すべてのメモを削除
28 | すべてのメモを削除しました!
29 | メモ #%d の操作を選択してください
30 |
31 |
32 | メモを保存
33 | 変更を保存しますか?
34 |
35 |
36 | メモ No: %d
37 | メモに本文はありません。
38 |
39 |
40 | OK
41 | キャンセル
42 |
43 |
44 | メモを作成しました
45 | メモを更新しました
46 | 最終更新
47 |
48 |
49 | 描画オプション:
50 | ブラシの色:
51 | ブラシのサイズ:
52 |
53 |
54 | 文字の色:
55 | スタイル:
56 |
57 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Notepad
3 | Add Note
4 | Delete note
5 | Search
6 | Format Text
7 | Done
8 | Show Keyboard
9 | Voice input
10 | Write Your note here…
11 | Delete all notes
12 | Test
13 | Speak now
14 |
15 | Erase All
16 | Brush
17 | Erase
18 | Paint
19 | Draw
20 |
21 |
22 | Search notes…
23 | Are you sure?
24 | Close Application
25 | Delete note #%d
26 | Note #%d deleted
27 | Delete all notes
28 | All notes have been deleted!
29 | Choose action for note #%d
30 |
31 |
32 | Save note
33 | Do you want to save changes?
34 |
35 |
36 | Note No: %d
37 | Note has no text.
38 |
39 |
40 |
41 | OK
42 | Cancel
43 |
44 |
45 | Note created
46 | Note updated
47 | Last updated
48 |
49 |
50 | Draw options:
51 | Brush color:
52 | Brush size:
53 |
54 |
55 | Text color:
56 | Style:
57 |
58 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/tomek/notepad/Note.java:
--------------------------------------------------------------------------------
1 | package com.example.tomek.notepad;
2 |
3 | import android.graphics.Bitmap;
4 | import android.text.Spannable;
5 |
6 | import java.text.DateFormat;
7 | import java.text.SimpleDateFormat;
8 | import java.util.Date;
9 | import java.util.Locale;
10 |
11 | /**
12 | * Class that represents single Note
13 | */
14 | public class Note {
15 |
16 | // KEY_ID of Note
17 | private int mId = -1;
18 |
19 | // Spannable used to format text
20 | private Spannable mSpannable;
21 |
22 | //
23 | private String mTitle;
24 |
25 | // Raw text used to make titles
26 | private String rawText;
27 |
28 | //Painting
29 | private Bitmap mImage;
30 |
31 | //Dates (Default value)
32 | private Date dateUpdated = new Date();
33 |
34 | //Formatter
35 | private static final DateFormat dt = new SimpleDateFormat("dd.MM.yyyy, hh:mm:ss", Locale.getDefault());
36 |
37 | public Note() {
38 |
39 | }
40 |
41 | public Note(int id, String title, Spannable spannable, Bitmap image, Date dateUpdated) {
42 | this.mId = id;
43 | this.mTitle = title;
44 | this.mSpannable = spannable;
45 | this.mImage = image;
46 | this.rawText = mSpannable.toString(); //TODO Remove this field and make this value accessible through utility method
47 | this.dateUpdated = dateUpdated;
48 | }
49 |
50 | public int getId() {
51 | return mId;
52 | }
53 |
54 | public String getTitle(){
55 | return mTitle;
56 | }
57 |
58 | public Spannable getSpannable() {
59 | return mSpannable;
60 | }
61 |
62 | public String getRawText() {
63 | return rawText;
64 | }
65 |
66 | public Bitmap getImage() {
67 | return mImage;
68 | }
69 |
70 | public Date getDateUpdated() {
71 | return dateUpdated;
72 | }
73 |
74 | public String getFormattedDateUpdatted() {
75 | return dt.format(dateUpdated);
76 | }
77 |
78 | public void setId(int id) {
79 | this.mId = id;
80 | }
81 |
82 | public void setSpannable(Spannable spannable) {
83 | this.mSpannable = spannable;
84 | }
85 |
86 | public void setTitle(String title) {
87 | this.mTitle = title;
88 | }
89 |
90 | public void setRawText(String rawText) {
91 | this.rawText = rawText;
92 | }
93 |
94 | public void setImage(Bitmap image) {
95 | this.mImage = image;
96 | }
97 |
98 | public void setDateUpdated(Date dateUpdated) {
99 | this.dateUpdated = dateUpdated;
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/app/src/main/res/values-pl/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Notatnik
3 | Notatka
4 | Usuń notatkę
5 | Szukaj
6 | Formatowanie Tekstu
7 | Akceptuj
8 | Pokaż klawiaturę
9 | Wprowadzanie głosowe
10 | Napisz swoją notatkę…
11 | Usuń wszystkie notatki
12 | Test
13 | Mów teraz
14 |
15 | Skasuj wszystko
16 | Pędzel
17 | Gumka
18 | Kolor
19 | Rysuj
20 |
21 |
22 | Szukaj notatek…
23 | Jesteś pewien?
24 | Zamknij aplikację
25 | Usuń notatkę #%d
26 | Notatka #%d została usunięta
27 | Usuń wszystkie notatki
28 | Wszystkie notatki zostały usunięte!
29 | Wybierz akcję dla notatki #%d
30 |
31 |
32 | Zapisz notatkę
33 | Czy chcesz zapisać zmiany?
34 |
35 |
36 | Notatka nr. %d
37 | Pusta notatka.
38 |
39 |
40 |
41 | OK
42 | Anuluj
43 |
44 |
45 | Notatka zapisana
46 | Notatka zmieniona
47 | Ostatnia zmiana
48 |
49 |
50 |
51 | Opcje rysowania:
52 | Kolor pędzla:
53 | Rozmiar pędzla:
54 |
55 |
56 | Kolor tekstu:
57 | Styl:
58 |
59 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/tomek/notepad/NoteAdapter.java:
--------------------------------------------------------------------------------
1 | package com.example.tomek.notepad;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.support.annotation.NonNull;
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 |
12 | import java.util.List;
13 |
14 | public class NoteAdapter extends ArrayAdapter {
15 |
16 | private Context context;
17 | private int layoutResourceId;
18 | private List data = null;
19 |
20 | public NoteAdapter(Context context, int layoutResourceId, List data) {
21 | super(context, layoutResourceId, data);
22 | this.layoutResourceId = layoutResourceId;
23 | this.context = context;
24 | this.data = data;
25 | }
26 |
27 | @Override
28 | @NonNull
29 | public View getView(int position, View convertView, @NonNull ViewGroup parent) {
30 | View row = convertView;
31 | NoteHolder holder;
32 |
33 | if(row == null)
34 | {
35 | LayoutInflater inflater = ((Activity)context).getLayoutInflater();
36 | row = inflater.inflate(layoutResourceId, parent, false);
37 |
38 | holder = new NoteHolder();
39 | holder.noteTitle = (TextView)row.findViewById(R.id.noteTitle);
40 | holder.noteContent = (TextView)row.findViewById(R.id.noteContent);
41 | holder.noteDate = (TextView)row.findViewById(R.id.noteDate);
42 |
43 |
44 | row.setTag(holder);
45 | }
46 | else
47 | {
48 | holder = (NoteHolder)row.getTag();
49 | }
50 |
51 | Note note = data.get(position);
52 | String noteTitle = note.getTitle();
53 | if (noteTitle == null || noteTitle.length() == 0)
54 | noteTitle = String.format(context.getString(R.string.note_number), note.getId());
55 | holder.noteTitle.setText(noteTitle);
56 |
57 | String title = note.getRawText();
58 | if (title.length() != 0) {
59 | holder.noteContent.setText(note.getRawText());
60 | }
61 | else {
62 | //TODO Finding out if there is picture on note
63 | holder.noteContent.setText("INFO: Note has no text");
64 | }
65 |
66 | holder.noteDate.setText(context.getString(R.string.last_updated) + ": " + note.getFormattedDateUpdatted());
67 |
68 | return row;
69 | }
70 |
71 | public void setData(List data) {
72 | this.data = data;
73 | }
74 |
75 | public List getData() {
76 | return data;
77 | }
78 |
79 | private static class NoteHolder
80 | {
81 | private TextView noteTitle;
82 | private TextView noteContent;
83 | private TextView noteDate;
84 | }
85 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/example/tomek/notepad/DrawingView.java:
--------------------------------------------------------------------------------
1 | package com.example.tomek.notepad;
2 |
3 | import android.content.Context;
4 | import android.graphics.Bitmap;
5 | import android.graphics.Canvas;
6 | import android.graphics.Color;
7 | import android.graphics.Paint;
8 | import android.graphics.Path;
9 | import android.graphics.PorterDuff;
10 | import android.graphics.PorterDuffXfermode;
11 | import android.util.AttributeSet;
12 | import android.util.TypedValue;
13 | import android.view.MotionEvent;
14 | import android.view.View;
15 |
16 | public class DrawingView extends View {
17 |
18 | //initial color
19 | private static final int DEFAULT_PAINT_COLOR = Color.BLACK;
20 | //drawing path
21 | private Path drawPath;
22 | //drawing and canvas paint
23 | private Paint drawPaint, canvasPaint;
24 | //canvas
25 | private Canvas drawCanvas;
26 | //canvas bitmap
27 | private Bitmap canvasBitmap;
28 | //brush size
29 | private float brushSize;
30 | //erase mode
31 | private boolean erase;
32 |
33 | public DrawingView(Context context, AttributeSet attrs){
34 | super(context, attrs);
35 | setupDrawing();
36 | }
37 |
38 | private void setupDrawing(){
39 | drawPath = new Path();
40 | drawPaint = new Paint();
41 |
42 | setBrushSize(10);
43 |
44 | drawPaint.setColor(DEFAULT_PAINT_COLOR);
45 |
46 | drawPaint.setAntiAlias(true);
47 | drawPaint.setStrokeWidth(brushSize);
48 | drawPaint.setStyle(Paint.Style.STROKE);
49 | drawPaint.setStrokeJoin(Paint.Join.ROUND);
50 | drawPaint.setStrokeCap(Paint.Cap.ROUND);
51 |
52 | canvasPaint = new Paint(Paint.DITHER_FLAG);
53 |
54 |
55 | }
56 |
57 | @Override
58 | protected void onSizeChanged(int w, int h, int oldw, int oldh) {
59 | super.onSizeChanged(w, h, oldw, oldh);
60 | if (canvasBitmap == null) {
61 | canvasBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
62 | drawCanvas = new Canvas(canvasBitmap);
63 | }
64 | else {
65 | canvasBitmap = Bitmap.createBitmap(canvasBitmap);
66 | canvasBitmap = canvasBitmap.copy(Bitmap.Config.ARGB_8888, true);
67 | drawCanvas = new Canvas(canvasBitmap);
68 | }
69 | }
70 |
71 | @Override
72 | protected void onDraw(Canvas canvas) {
73 | canvas.drawBitmap(canvasBitmap, 0, 0, canvasPaint);
74 | canvas.drawPath(drawPath, drawPaint);
75 | }
76 |
77 | public boolean draw(float x, float y, int motionAction) {
78 | switch (motionAction) {
79 | case MotionEvent.ACTION_DOWN:
80 | drawPath.moveTo(x, y);
81 | break;
82 | case MotionEvent.ACTION_MOVE:
83 | drawPath.lineTo(x, y);
84 | break;
85 | case MotionEvent.ACTION_UP:
86 | drawCanvas.drawPath(drawPath, drawPaint);
87 | drawPath.reset();
88 | break;
89 | default:
90 | return false;
91 | }
92 | invalidate();
93 | return true;
94 | }
95 |
96 | @Override
97 | public boolean onTouchEvent(MotionEvent event) {
98 | return draw(event.getX(), event.getY(), event.getAction());
99 | }
100 |
101 | public void startNew(){
102 | drawCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
103 | invalidate();
104 | }
105 |
106 | public void setPaintColor(int paintColor) {
107 | drawPaint.setColor(paintColor);
108 | }
109 |
110 | public void setBrushSize(float size) {
111 |
112 | // pixel
113 | brushSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
114 | size, getResources().getDisplayMetrics());
115 | drawPaint.setStrokeWidth(brushSize);
116 |
117 | }
118 |
119 | public void setErase(boolean isErase){
120 | erase = isErase;
121 |
122 | if(erase) {
123 | drawPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
124 | }
125 | else {
126 | drawPaint.setXfermode(null);
127 | }
128 | }
129 |
130 | public Bitmap getCanvasBitmap() {
131 | return canvasBitmap;
132 | }
133 |
134 | public void setBitmap(Bitmap bmp) {
135 | canvasBitmap = bmp;
136 | }
137 | }
138 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/example/tomek/notepad/DatabaseTestCase.java:
--------------------------------------------------------------------------------
1 | package com.example.tomek.notepad;
2 |
3 | import android.content.Context;
4 | import android.graphics.Bitmap;
5 | import android.support.test.InstrumentationRegistry;
6 | import android.support.test.runner.AndroidJUnit4;
7 | import android.text.Spannable;
8 | import android.text.SpannableString;
9 |
10 | import org.junit.After;
11 | import org.junit.Before;
12 | import org.junit.Test;
13 | import org.junit.runner.RunWith;
14 |
15 | import java.util.ArrayList;
16 |
17 | import static junit.framework.Assert.assertTrue;
18 | import static org.hamcrest.MatcherAssert.assertThat;
19 | import static org.hamcrest.Matchers.empty;
20 | import static org.hamcrest.Matchers.hasSize;
21 | import static org.hamcrest.Matchers.is;
22 |
23 | @RunWith(AndroidJUnit4.class)
24 | public class DatabaseTestCase {
25 |
26 | @Before
27 | public void setup() {
28 | Context appContext = InstrumentationRegistry.getTargetContext();
29 | DatabaseHandler databaseHandler = new DatabaseHandler(appContext);
30 | databaseHandler.clearAllNotes();
31 | }
32 |
33 | @After
34 | public void cleanup() {
35 | Context appContext = InstrumentationRegistry.getTargetContext();
36 | DatabaseHandler databaseHandler = new DatabaseHandler(appContext);
37 | databaseHandler.clearAllNotes();
38 | }
39 |
40 | @Test
41 | public void shouldInsertNoteToDb() {
42 | Context appContext = InstrumentationRegistry.getTargetContext();
43 |
44 | // Database instance
45 | DatabaseHandler databaseHandler = new DatabaseHandler(appContext);
46 |
47 | // Properties of note to be added
48 | final String title = "Some random title :)";
49 | final Spannable text = new SpannableString("Some note text");
50 | final int bmp_width = 1000;
51 | final int bmp_height = 1000;
52 | final Bitmap bmp = Bitmap.createBitmap(bmp_width, bmp_height, Bitmap.Config.ARGB_8888);
53 |
54 | // Note that will be added
55 | Note noteToAdd = new Note();
56 | noteToAdd.setTitle(title);
57 | noteToAdd.setSpannable(text);
58 | noteToAdd.setImage(bmp);
59 |
60 | // Fetch notes from DB
61 | ArrayList notesInDb = databaseHandler.getAllNotesAsArrayList();
62 |
63 | // Check if DB is empty
64 | assertThat(notesInDb, is(empty()));
65 |
66 | // Add note to DB
67 | databaseHandler.createNote(noteToAdd);
68 |
69 | // Fetch notes from DB
70 | notesInDb = databaseHandler.getAllNotesAsArrayList();
71 |
72 | // Check if note was added
73 | assertThat(notesInDb, hasSize(1));
74 |
75 | // Get fetched note instance
76 | Note noteFromDb = notesInDb.get(0);
77 |
78 | databaseHandler.getNote(noteFromDb.getId());
79 |
80 | // Check if added note contains same properties
81 | assertThat(noteFromDb.getTitle(), is(title));
82 | assertThat(noteFromDb.getSpannable(), is(text));
83 | assertTrue(noteFromDb.getImage().sameAs(bmp));
84 |
85 | }
86 |
87 | @Test
88 | public void shouldInsertManyNotesToDb() {
89 |
90 | final int notesCount = 1000;
91 |
92 | Context appContext = InstrumentationRegistry.getTargetContext();
93 |
94 | // Database instance
95 | DatabaseHandler databaseHandler = new DatabaseHandler(appContext);
96 |
97 | // Properties of note to be added
98 | final String title = "Some random title :)";
99 | final Spannable text = new SpannableString("Some note text");
100 | final int bmp_width = 1000;
101 | final int bmp_height = 1000;
102 | final Bitmap bmp = Bitmap.createBitmap(bmp_width, bmp_height, Bitmap.Config.ARGB_8888);
103 |
104 | // Note that will be added
105 | Note noteToAdd = new Note();
106 | noteToAdd.setTitle(title);
107 | noteToAdd.setSpannable(text);
108 | noteToAdd.setImage(bmp);
109 |
110 | // Fetch notes from DB
111 | ArrayList notesInDb = databaseHandler.getAllNotesAsArrayList();
112 |
113 | // Check if DB is empty
114 | assertThat(notesInDb, is(empty()));
115 |
116 | // Add notes to DB
117 | for (int i = 0; i < notesCount; i++) {
118 | databaseHandler.createNote(noteToAdd);
119 | if (i%10 == 0) System.out.println("TEST NOTE: " + i);
120 | }
121 |
122 | // Fetch notes from DB
123 | notesInDb = databaseHandler.getAllNotesAsArrayList();
124 |
125 | // Check if note was added
126 | assertThat(notesInDb, hasSize(1000));
127 |
128 | // Get fetched note instance
129 | Note noteFromDb = notesInDb.get(0);
130 |
131 | databaseHandler.getNote(noteFromDb.getId());
132 |
133 | // Check if added note contains same properties
134 | assertThat(noteFromDb.getTitle(), is(title));
135 | assertThat(noteFromDb.getSpannable(), is(text));
136 | assertTrue(noteFromDb.getImage().sameAs(bmp));
137 |
138 | }
139 |
140 | }
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/content_text_format.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 |
18 |
19 |
23 |
24 |
25 |
35 |
36 |
42 |
43 |
52 |
53 |
62 |
63 |
72 |
73 |
82 |
83 |
92 |
93 |
94 |
95 |
105 |
106 |
112 |
113 |
122 |
123 |
132 |
133 |
142 |
143 |
144 |
145 |
146 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/content_draw_panel.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
16 |
17 |
21 |
22 |
31 |
32 |
38 |
39 |
46 |
47 |
55 |
56 |
64 |
65 |
66 |
67 |
76 |
77 |
83 |
84 |
92 |
93 |
101 |
102 |
110 |
111 |
119 |
120 |
128 |
129 |
130 |
131 |
140 |
141 |
147 |
148 |
156 |
157 |
165 |
166 |
174 |
175 |
176 |
177 |
178 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU LESSER GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 |
9 | This version of the GNU Lesser General Public License incorporates
10 | the terms and conditions of version 3 of the GNU General Public
11 | License, supplemented by the additional permissions listed below.
12 |
13 | 0. Additional Definitions.
14 |
15 | As used herein, "this License" refers to version 3 of the GNU Lesser
16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU
17 | General Public License.
18 |
19 | "The Library" refers to a covered work governed by this License,
20 | other than an Application or a Combined Work as defined below.
21 |
22 | An "Application" is any work that makes use of an interface provided
23 | by the Library, but which is not otherwise based on the Library.
24 | Defining a subclass of a class defined by the Library is deemed a mode
25 | of using an interface provided by the Library.
26 |
27 | A "Combined Work" is a work produced by combining or linking an
28 | Application with the Library. The particular version of the Library
29 | with which the Combined Work was made is also called the "Linked
30 | Version".
31 |
32 | The "Minimal Corresponding Source" for a Combined Work means the
33 | Corresponding Source for the Combined Work, excluding any source code
34 | for portions of the Combined Work that, considered in isolation, are
35 | based on the Application, and not on the Linked Version.
36 |
37 | The "Corresponding Application Code" for a Combined Work means the
38 | object code and/or source code for the Application, including any data
39 | and utility programs needed for reproducing the Combined Work from the
40 | Application, but excluding the System Libraries of the Combined Work.
41 |
42 | 1. Exception to Section 3 of the GNU GPL.
43 |
44 | You may convey a covered work under sections 3 and 4 of this License
45 | without being bound by section 3 of the GNU GPL.
46 |
47 | 2. Conveying Modified Versions.
48 |
49 | If you modify a copy of the Library, and, in your modifications, a
50 | facility refers to a function or data to be supplied by an Application
51 | that uses the facility (other than as an argument passed when the
52 | facility is invoked), then you may convey a copy of the modified
53 | version:
54 |
55 | a) under this License, provided that you make a good faith effort to
56 | ensure that, in the event an Application does not supply the
57 | function or data, the facility still operates, and performs
58 | whatever part of its purpose remains meaningful, or
59 |
60 | b) under the GNU GPL, with none of the additional permissions of
61 | this License applicable to that copy.
62 |
63 | 3. Object Code Incorporating Material from Library Header Files.
64 |
65 | The object code form of an Application may incorporate material from
66 | a header file that is part of the Library. You may convey such object
67 | code under terms of your choice, provided that, if the incorporated
68 | material is not limited to numerical parameters, data structure
69 | layouts and accessors, or small macros, inline functions and templates
70 | (ten or fewer lines in length), you do both of the following:
71 |
72 | a) Give prominent notice with each copy of the object code that the
73 | Library is used in it and that the Library and its use are
74 | covered by this License.
75 |
76 | b) Accompany the object code with a copy of the GNU GPL and this license
77 | document.
78 |
79 | 4. Combined Works.
80 |
81 | You may convey a Combined Work under terms of your choice that,
82 | taken together, effectively do not restrict modification of the
83 | portions of the Library contained in the Combined Work and reverse
84 | engineering for debugging such modifications, if you also do each of
85 | the following:
86 |
87 | a) Give prominent notice with each copy of the Combined Work that
88 | the Library is used in it and that the Library and its use are
89 | covered by this License.
90 |
91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license
92 | document.
93 |
94 | c) For a Combined Work that displays copyright notices during
95 | execution, include the copyright notice for the Library among
96 | these notices, as well as a reference directing the user to the
97 | copies of the GNU GPL and this license document.
98 |
99 | d) Do one of the following:
100 |
101 | 0) Convey the Minimal Corresponding Source under the terms of this
102 | License, and the Corresponding Application Code in a form
103 | suitable for, and under terms that permit, the user to
104 | recombine or relink the Application with a modified version of
105 | the Linked Version to produce a modified Combined Work, in the
106 | manner specified by section 6 of the GNU GPL for conveying
107 | Corresponding Source.
108 |
109 | 1) Use a suitable shared library mechanism for linking with the
110 | Library. A suitable mechanism is one that (a) uses at run time
111 | a copy of the Library already present on the user's computer
112 | system, and (b) will operate properly with a modified version
113 | of the Library that is interface-compatible with the Linked
114 | Version.
115 |
116 | e) Provide Installation Information, but only if you would otherwise
117 | be required to provide such information under section 6 of the
118 | GNU GPL, and only to the extent that such information is
119 | necessary to install and execute a modified version of the
120 | Combined Work produced by recombining or relinking the
121 | Application with a modified version of the Linked Version. (If
122 | you use option 4d0, the Installation Information must accompany
123 | the Minimal Corresponding Source and Corresponding Application
124 | Code. If you use option 4d1, you must provide the Installation
125 | Information in the manner specified by section 6 of the GNU GPL
126 | for conveying Corresponding Source.)
127 |
128 | 5. Combined Libraries.
129 |
130 | You may place library facilities that are a work based on the
131 | Library side by side in a single library together with other library
132 | facilities that are not Applications and are not covered by this
133 | License, and convey such a combined library under terms of your
134 | choice, if you do both of the following:
135 |
136 | a) Accompany the combined library with a copy of the same work based
137 | on the Library, uncombined with any other library facilities,
138 | conveyed under the terms of this License.
139 |
140 | b) Give prominent notice with the combined library that part of it
141 | is a work based on the Library, and explaining where to find the
142 | accompanying uncombined form of the same work.
143 |
144 | 6. Revised Versions of the GNU Lesser General Public License.
145 |
146 | The Free Software Foundation may publish revised and/or new versions
147 | of the GNU Lesser General Public License from time to time. Such new
148 | versions will be similar in spirit to the present version, but may
149 | differ in detail to address new problems or concerns.
150 |
151 | Each version is given a distinguishing version number. If the
152 | Library as you received it specifies that a certain numbered version
153 | of the GNU Lesser General Public License "or any later version"
154 | applies to it, you have the option of following the terms and
155 | conditions either of that published version or of any later version
156 | published by the Free Software Foundation. If the Library as you
157 | received it does not specify a version number of the GNU Lesser
158 | General Public License, you may choose any version of the GNU Lesser
159 | General Public License ever published by the Free Software Foundation.
160 |
161 | If the Library as you received it specifies that a proxy can decide
162 | whether future versions of the GNU Lesser General Public License shall
163 | apply, that proxy's public statement of acceptance of any version is
164 | permanent authorization for you to choose that version for the
165 | Library.
166 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/tomek/notepad/DatabaseHandler.java:
--------------------------------------------------------------------------------
1 | package com.example.tomek.notepad;
2 |
3 | import android.content.ContentValues;
4 | import android.content.Context;
5 | import android.database.Cursor;
6 | import android.database.DatabaseUtils;
7 | import android.database.sqlite.SQLiteDatabase;
8 | import android.database.sqlite.SQLiteException;
9 | import android.database.sqlite.SQLiteOpenHelper;
10 | import android.graphics.Bitmap;
11 | import android.text.Html;
12 | import android.text.Spannable;
13 | import android.text.SpannableString;
14 | import android.text.Spanned;
15 | import android.text.SpannedString;
16 |
17 | import java.text.DateFormat;
18 | import java.text.SimpleDateFormat;
19 | import java.util.ArrayList;
20 | import java.util.Date;
21 | import java.util.Locale;
22 |
23 | /**
24 | * DatabaseHandler class used for Creating, Accessing and Modifying SQLite Database
25 | */
26 | public class DatabaseHandler extends SQLiteOpenHelper {
27 |
28 | // TODO: Try not to exec SQL directly, prevent from SQL injects
29 |
30 | private static final int DATABASE_VERSION = 3;
31 | private static final String DATABASE_NAME = "notepadDatabase";
32 | private static final String TABLE_NOTES = "notes";
33 | private static final String KEY_ID = "id";
34 | private static final String KEY_NOTE_TITLE = "noteTitle";
35 | private static final String KEY_SPANNABLE_NOTE = "serializedSpannableNote";
36 | private static final String KEY_IMAGE = "image";
37 | private static final String KEY_DATE_UPDATED = "dateUpdated";
38 | private static final DateFormat dt = new SimpleDateFormat("dd.MM.yyyy, hh:mm:ss", Locale.getDefault());
39 |
40 | public DatabaseHandler(Context context) {
41 | super(context, DATABASE_NAME, null, DATABASE_VERSION);
42 | }
43 |
44 | @Override
45 | public void onCreate(SQLiteDatabase db) {
46 | db.execSQL("CREATE TABLE IF NOT EXISTS " + TABLE_NOTES + "("
47 | + KEY_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
48 | + KEY_SPANNABLE_NOTE + " TEXT, "
49 | + KEY_IMAGE + " BLOB, "
50 | + KEY_DATE_UPDATED + " TEXT, "
51 | + KEY_NOTE_TITLE + " VARCHAR(100))" //We don't want a super long title...
52 | );
53 | }
54 |
55 | @Override
56 | public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
57 |
58 | switch (oldVersion)
59 | {
60 | case 1:
61 | //upgrade from version 1 to 2
62 | db.execSQL("ALTER TABLE " + TABLE_NOTES + " ADD COLUMN " + KEY_DATE_UPDATED + " TEXT;");
63 | case 2:
64 | //upgrade from version 2 to 3
65 | db.execSQL("ALTER TABLE " + TABLE_NOTES + " ADD COLUMN " + KEY_NOTE_TITLE + " VARCHAR(100);");
66 | case 3:
67 | //upgrade from version 3 to 4
68 | //db.execSQL();
69 |
70 | //and so on.. do not add breaks so that switch will
71 | //start at oldVersion, and run straight through to the latest
72 |
73 | }
74 | }
75 |
76 | /**
77 | * Method used to clear notes table
78 | */
79 | public void clearAllNotes() {
80 | SQLiteDatabase db = getWritableDatabase();
81 | db.execSQL("DELETE FROM " + TABLE_NOTES);
82 | }
83 |
84 | /**
85 | * Method used to put Note object into Database
86 | * @param note Note object to put into DB
87 | */
88 | public void createNote(Note note) {
89 | SQLiteDatabase db = getWritableDatabase();
90 | String spannableAsHtml = convertSpannableToHtmlString(note.getSpannable());
91 | String date = dt.format(new Date());
92 |
93 | ContentValues values = new ContentValues();
94 |
95 | values.put(KEY_SPANNABLE_NOTE, spannableAsHtml);
96 | values.put(KEY_NOTE_TITLE, note.getTitle());
97 | values.put(KEY_IMAGE, BitmapConverter.getBytes(note.getImage()));
98 | values.put(KEY_DATE_UPDATED, date);
99 |
100 | db.insert(TABLE_NOTES, null, values);
101 | db.close();
102 | }
103 |
104 | /**
105 | * Method used to get specified Note from Database
106 | * @param id KEY_ID of Note to get from Database
107 | * @return Note object with specified KEY_ID
108 | */
109 | public Note getNote(int id) throws SQLiteException {
110 | SQLiteDatabase db = getReadableDatabase();
111 |
112 | Cursor cursor = db.query(TABLE_NOTES, new String[]{KEY_ID, KEY_SPANNABLE_NOTE, KEY_IMAGE, KEY_DATE_UPDATED, KEY_NOTE_TITLE}, KEY_ID + "=?",
113 | new String[]{String.valueOf(id)}, null, null, null, null);
114 |
115 | if (!cursor.moveToFirst()) {
116 | //Failed to load note. Maybe the user restored data from an incompatible backup?
117 | //Let's delete the problematic data
118 | deleteNote(id);
119 | throw new SQLiteException("Note doesn't exist");
120 | }
121 |
122 | String spannableAsHtml = cursor.getString(cursor.getColumnIndex(KEY_SPANNABLE_NOTE));
123 | Spannable spannable = convertHtmlStringToSpannable(spannableAsHtml);
124 |
125 | Bitmap image = BitmapConverter.getImage(cursor.getBlob(cursor.getColumnIndex(KEY_IMAGE)));
126 |
127 | Date date;
128 |
129 | try {
130 | date = dt.parse(cursor.getString(cursor.getColumnIndex(KEY_DATE_UPDATED)));
131 | } catch (Exception e) {
132 | date = new Date();
133 | e.printStackTrace();
134 | }
135 |
136 | String title;
137 | try {
138 | title = cursor.getString(cursor.getColumnIndex(KEY_NOTE_TITLE));
139 | }catch (Exception e){
140 | title = "";
141 | e.printStackTrace();
142 | }
143 |
144 | db.close();
145 | cursor.close();
146 | return new Note(id, title, spannable, image, date);
147 | }
148 |
149 | /**
150 | * Method used to delete specified Note from Database
151 | * @param note Note to delete
152 | */
153 | public void deleteNote(Note note) {
154 | deleteNote(note.getId());
155 | }
156 |
157 | public void deleteNote(int noteId) {
158 | SQLiteDatabase db = getWritableDatabase();
159 | db.delete(TABLE_NOTES, KEY_ID + "=?", new String[]{String.valueOf(noteId)});
160 | db.close();
161 | }
162 |
163 | /**
164 | * Method used to get count of notes in Database
165 | * @return count of notes in Database
166 | */
167 | public int getNoteCount() {
168 | SQLiteDatabase db = getReadableDatabase();
169 | int numberOfNotes = (int) DatabaseUtils.queryNumEntries(db, TABLE_NOTES);
170 | db.close();
171 | return numberOfNotes;
172 | }
173 |
174 | /**
175 | * Method used to update Note's text/format
176 | * @param note Note to update
177 | * @return updated Note
178 | */
179 | public int updateNote(Note note) {
180 | SQLiteDatabase db = getWritableDatabase();
181 |
182 | String spannableAsHtml = convertSpannableToHtmlString(note.getSpannable());
183 |
184 | String date = dt.format(new Date());
185 |
186 | ContentValues values = new ContentValues();
187 | values.put(KEY_IMAGE, BitmapConverter.getBytes(note.getImage()));
188 | values.put(KEY_DATE_UPDATED, date);
189 | values.put(KEY_SPANNABLE_NOTE, spannableAsHtml);
190 | values.put(KEY_NOTE_TITLE, note.getTitle());
191 |
192 | return db.update(TABLE_NOTES, values, KEY_ID + "=?", new String[]{String.valueOf(note.getId())});
193 | }
194 |
195 | /**
196 | * Method used to get all notes in Database
197 | * @return ArrayList of Notes, containing all notes in Database
198 | */
199 | public ArrayList getAllNotesAsArrayList() {
200 | ArrayList notes = new ArrayList<>();
201 |
202 | SQLiteDatabase db = getWritableDatabase();
203 | Cursor cursor = db.rawQuery("SELECT * FROM " + TABLE_NOTES, null);
204 |
205 | if (cursor.moveToFirst()) {
206 | do {
207 | int id = Integer.parseInt(cursor.getString(cursor.getColumnIndex(KEY_ID)));
208 | Spannable spannable = convertHtmlStringToSpannable(cursor.getString(cursor.getColumnIndex(KEY_SPANNABLE_NOTE)));
209 | //Default val
210 | Date date;
211 |
212 | try {
213 | date = dt.parse(cursor.getString(cursor.getColumnIndex(KEY_DATE_UPDATED)));
214 | } catch (Exception e) {
215 | date = new Date();
216 | e.printStackTrace();
217 | }
218 |
219 | String title;
220 | try {
221 | title = cursor.getString(cursor.getColumnIndex(KEY_NOTE_TITLE));
222 | } catch (Exception e) {
223 | title = "";
224 | e.printStackTrace();
225 | }
226 |
227 | Note note = new Note(id, title, spannable, null, date);
228 | notes.add(note);
229 | }
230 | while (cursor.moveToNext());
231 | }
232 | cursor.close();
233 | return notes;
234 | }
235 |
236 | private Spannable convertHtmlStringToSpannable(String htmlString) {
237 | Spanned spanned;
238 | if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
239 | spanned = Html.fromHtml(htmlString, Html.FROM_HTML_MODE_LEGACY);
240 | } else {
241 | spanned = Html.fromHtml(htmlString);
242 | }
243 |
244 | final String newLine = "\n";
245 | // Html.toHtml() appends newLine to end of text.
246 | // This is workaround for that situation.
247 | while (spanned.toString().endsWith(newLine)) {
248 | spanned = new SpannedString(spanned.subSequence(0, spanned.length() - newLine.length()));
249 | }
250 | return new SpannableString(spanned);
251 | }
252 |
253 | private String convertSpannableToHtmlString(Spannable spannable) {
254 | String htmlString;
255 | if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
256 | htmlString = Html.toHtml(spannable, Html.FROM_HTML_MODE_LEGACY);
257 | } else {
258 | htmlString = Html.toHtml(spannable);
259 | }
260 | return removeAllSuffixingNewlines(htmlString);
261 | }
262 |
263 | private String removeAllSuffixingNewlines(String string) {
264 | // Html.toHtml() appends newLine to end of text.
265 | // This is workaround for that situation.
266 | final String newLine = "\n";
267 | while (string.lastIndexOf(newLine) != -1
268 | && string.lastIndexOf(newLine) == string.length() - newLine.length()) {
269 | string = string.substring(0, string.length() - newLine.length());
270 | }
271 | return string;
272 | }
273 |
274 | }
275 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/tomek/notepad/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.example.tomek.notepad;
2 |
3 | import android.app.AlertDialog;
4 | import android.content.Context;
5 | import android.content.DialogInterface;
6 | import android.content.Intent;
7 | import android.os.Bundle;
8 | import android.support.design.widget.FloatingActionButton;
9 | import android.support.v7.app.AppCompatActivity;
10 | import android.support.v7.widget.Toolbar;
11 | import android.view.ContextMenu;
12 | import android.view.MenuInflater;
13 | import android.view.View;
14 | import android.view.Menu;
15 | import android.view.MenuItem;
16 | import android.view.inputmethod.InputMethodManager;
17 | import android.widget.AdapterView;
18 | import android.widget.ListView;
19 | import android.widget.SearchView;
20 | import android.widget.Toast;
21 |
22 | import java.util.ArrayList;
23 |
24 | /**
25 | * Main Activity class
26 | */
27 | public class MainActivity extends AppCompatActivity {
28 |
29 | // Array used to backup data before using search function
30 | private ArrayList allNotesSearchArray;
31 |
32 | // Database Handler
33 | private DatabaseHandler dbHandler;
34 |
35 | // Alert dialogs for back button and delete all notes button
36 | private AlertDialog alertDialogDeleteAll;
37 | private AlertDialog alertDialogDeleteSingleNote;
38 |
39 | // Note selected on menu
40 | private Note selectedNote;
41 |
42 | // Variables used to handle note list
43 | public static NoteAdapter noteAdapter;
44 | public static ListView listView;
45 |
46 | @Override
47 | protected void onCreate(Bundle savedInstanceState) {
48 | super.onCreate(savedInstanceState);
49 | setContentView(R.layout.activity_main);
50 | Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
51 | setSupportActionBar(toolbar);
52 |
53 | // Create DatabaseHandler
54 | dbHandler = new DatabaseHandler(getApplicationContext());
55 |
56 | // Add items to ListView
57 | listView = (ListView) findViewById(R.id.listView);
58 | populateListView(dbHandler.getAllNotesAsArrayList());
59 |
60 | // Assign listView to context menu
61 | registerForContextMenu(listView);
62 |
63 | // Setup AlertDialogs
64 | alertDialogDeleteAll = initAlertDialogDeleteAllNotes();
65 |
66 | // Floating Action Button listener used to adding new notes
67 | FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
68 | fab.setOnClickListener(new View.OnClickListener() {
69 | @Override
70 | public void onClick(View view) {
71 | hideSoftKeyboard();
72 | Intent intent = new Intent(MainActivity.this, NoteActivity.class);
73 | intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
74 | intent.putExtra("id", "-1");
75 | startActivity(intent);
76 | }
77 | });
78 |
79 | listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
80 | public void onItemClick(AdapterView> parent, View view, int position, long id) {
81 | selectedNote = (Note) parent.getAdapter().getItem(position);
82 | editNote(selectedNote.getId());
83 | }
84 | });
85 | }
86 |
87 | @Override
88 | public boolean onCreateOptionsMenu(Menu menu) {
89 | // Creating menu
90 | getMenuInflater().inflate(R.menu.menu_main, menu);
91 |
92 | SearchView searchView = (SearchView) menu.findItem(R.id.search).getActionView();
93 | searchView.setQueryHint(searchView.getContext().getResources().getString(R.string.search_hint));
94 |
95 | searchView.setOnSearchClickListener(new View.OnClickListener() {
96 | @Override
97 | public void onClick(View v) {
98 | allNotesSearchArray = (ArrayList) noteAdapter.getData();
99 | }
100 | });
101 |
102 | final SearchView.OnQueryTextListener queryTextListener = new SearchView.OnQueryTextListener() {
103 | @Override
104 | public boolean onQueryTextChange(String newText) {
105 |
106 | ArrayList filteredNotesArrayList = new ArrayList<>();
107 | for (Note note : allNotesSearchArray) {
108 | if (note.getRawText().contains(newText)) {
109 | filteredNotesArrayList.add(note);
110 | }
111 | }
112 |
113 | populateListView(filteredNotesArrayList);
114 | noteAdapter.notifyDataSetChanged();
115 |
116 | return true;
117 | }
118 |
119 | @Override
120 | public boolean onQueryTextSubmit(String query) {
121 | // Do nothing
122 | return true;
123 | }
124 | };
125 | searchView.setOnQueryTextListener(queryTextListener);
126 |
127 | return true;
128 | }
129 |
130 | /**
131 | * Method used for first setup of delete all notes button AlertDialog
132 | */
133 | private AlertDialog initAlertDialogDeleteAllNotes() {
134 |
135 | AlertDialog.Builder builder = new AlertDialog.Builder(this);
136 | builder.setMessage(this.getString(R.string.confirmation)).setTitle(this.getString(R.string.delete_notes_title));
137 | builder.setPositiveButton(this.getString(R.string.ok_button), new DialogInterface.OnClickListener() {
138 | @Override
139 | public void onClick(DialogInterface dialog, int which) {
140 | deleteAllNotes();
141 | Toast.makeText(MainActivity.this, getString(R.string.delete_notes_success),
142 | Toast.LENGTH_SHORT).show();
143 | }
144 | });
145 |
146 | builder.setNegativeButton(this.getString(R.string.cancel_button), new DialogInterface.OnClickListener() {
147 | @Override
148 | public void onClick(DialogInterface dialog, int which) {
149 |
150 | }
151 | });
152 | return builder.create();
153 | }
154 |
155 | /**
156 | * Method used for setup of delete single note button AlertDialog
157 | */
158 | private AlertDialog setupAlertDialogDeleteSingleNote() {
159 |
160 | AlertDialog.Builder builder = new AlertDialog.Builder(this);
161 | builder.setMessage(this.getString(R.string.confirmation)).setTitle(String.format(this.getString(R.string.delete_note_number), selectedNote.getId()));
162 | builder.setPositiveButton(this.getString(R.string.ok_button), new DialogInterface.OnClickListener() {
163 | @Override
164 | public void onClick(DialogInterface dialog, int which) {
165 | dbHandler.deleteNote(selectedNote);
166 | noteAdapter.remove(selectedNote);
167 | noteAdapter.notifyDataSetChanged();
168 | Toast.makeText(MainActivity.this, String.format(getString(R.string.note_deleted), selectedNote.getId()),
169 | Toast.LENGTH_SHORT).show();
170 | }
171 | });
172 |
173 | builder.setNegativeButton(this.getString(R.string.cancel_button), new DialogInterface.OnClickListener() {
174 | @Override
175 | public void onClick(DialogInterface dialog, int which) {
176 |
177 | }
178 | });
179 | return builder.create();
180 | }
181 |
182 | /**
183 | * Method used to show AlertDialog when delete all notes button is clicked
184 | */
185 | public void showAlertDialogDeleteAllNotes(MenuItem menuItem) {
186 | alertDialogDeleteAll.show();
187 | }
188 |
189 | /**
190 | * Method used to show AlertDialog when delete note button is clicked
191 | */
192 | private void showAlertDialogDeleteSingleNote() {
193 | alertDialogDeleteSingleNote.show();
194 | }
195 |
196 | /**
197 | * Method used to delete all notes via DatabaseHandler
198 | */
199 | public void deleteAllNotes() {
200 | dbHandler.clearAllNotes();
201 | noteAdapter.clear();
202 | noteAdapter.notifyDataSetChanged();
203 | }
204 |
205 | /**
206 | * Method used to enter note edition mode
207 | *
208 | * @param noteId ID number of the Note entry in the SQLite database
209 | */
210 | private void editNote(int noteId) {
211 | hideSoftKeyboard();
212 | Intent intent = new Intent(MainActivity.this, NoteActivity.class);
213 | intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
214 | intent.putExtra("id", String.valueOf(noteId));
215 | startActivity(intent);
216 | }
217 |
218 | /**
219 | * Method used to hide keyboard
220 | */
221 | private void hideSoftKeyboard() {
222 | if (this.getCurrentFocus() != null) {
223 | try {
224 | InputMethodManager imm = (InputMethodManager) this.getSystemService(Context.INPUT_METHOD_SERVICE);
225 | imm.hideSoftInputFromWindow(this.getCurrentFocus().getApplicationWindowToken(), 0);
226 | } catch (RuntimeException e) {
227 | //ignore
228 | }
229 | }
230 | }
231 |
232 | /**
233 | * Method used to fill ListView
234 | *
235 | * @param note Array of Notes containing all Notes in Database
236 | */
237 | void populateListView(ArrayList note) {
238 | noteAdapter = new NoteAdapter(this,
239 | R.layout.listview_item_row, note);
240 | listView.setAdapter(noteAdapter);
241 | }
242 |
243 | public void setListViewData(ArrayList allNotes, Note newNote) {
244 | if (noteAdapter != null) {
245 | if (newNote != null){
246 | noteAdapter.add(newNote);
247 | }
248 | noteAdapter.setData(allNotes);
249 | noteAdapter.notifyDataSetChanged();
250 | }
251 | }
252 |
253 | @Override
254 | public void onCreateContextMenu(ContextMenu menu, View v,
255 | ContextMenu.ContextMenuInfo menuInfo) {
256 | super.onCreateContextMenu(menu, v, menuInfo);
257 |
258 | if (v.getId() == R.id.listView) {
259 | ListView listViewLocal = (ListView) v;
260 | AdapterView.AdapterContextMenuInfo acmi = (AdapterView.AdapterContextMenuInfo) menuInfo;
261 | selectedNote = (Note) listViewLocal.getItemAtPosition(acmi.position);
262 | menu.setHeaderTitle(String.format(v.getContext().getString(R.string.choose_activity), selectedNote.getId()));
263 | MenuInflater inflater = getMenuInflater();
264 | inflater.inflate(R.menu.context_menu_note_select, menu);
265 | }
266 | }
267 |
268 | @Override
269 | public boolean onContextItemSelected(MenuItem item) {
270 |
271 | switch (item.getItemId()) {
272 | case R.id.context_menu_delete:
273 | alertDialogDeleteSingleNote = setupAlertDialogDeleteSingleNote();
274 | showAlertDialogDeleteSingleNote();
275 | break;
276 | case R.id.context_menu_edit:
277 | editNote(selectedNote.getId());
278 | break;
279 | }
280 | return super.onContextItemSelected(item);
281 | }
282 |
283 | }
284 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/tomek/notepad/NoteActivity.java:
--------------------------------------------------------------------------------
1 | package com.example.tomek.notepad;
2 |
3 | import android.app.AlertDialog;
4 | import android.content.Context;
5 | import android.content.DialogInterface;
6 | import android.content.Intent;
7 | import android.database.sqlite.SQLiteException;
8 | import android.graphics.Color;
9 | import android.graphics.Point;
10 | import android.graphics.Typeface;
11 | import android.os.Build;
12 | import android.speech.RecognizerIntent;
13 | import android.support.annotation.Nullable;
14 | import android.support.v7.app.AppCompatActivity;
15 | import android.os.Bundle;
16 | import android.text.InputType;
17 | import android.text.Spannable;
18 | import android.text.Spanned;
19 | import android.text.SpannedString;
20 | import android.text.TextUtils;
21 | import android.text.style.ForegroundColorSpan;
22 | import android.text.style.StyleSpan;
23 | import android.text.style.UnderlineSpan;
24 | import android.view.ActionMode;
25 | import android.view.Display;
26 | import android.view.Menu;
27 | import android.view.MenuItem;
28 | import android.view.MotionEvent;
29 | import android.view.View;
30 | import android.view.ViewGroup;
31 | import android.view.WindowManager;
32 | import android.view.inputmethod.InputMethodManager;
33 | import android.widget.EditText;
34 | import android.widget.LinearLayout;
35 |
36 | import java.util.ArrayList;
37 | import java.util.Date;
38 |
39 | /**
40 | * Note Activity class that handles:
41 | * - New notes creation,
42 | * - Updating existing ones,
43 | * - Deleting existing ones if text is changed to blank
44 | * - Text formatting
45 | * - Drawing
46 | */
47 | public class NoteActivity extends AppCompatActivity {
48 |
49 | //TODO fix bug that adds two empty lines into loaded note (fixed like a retard)
50 | //TODO Enable choice of voice matches?
51 | //TODO Voice input text from cursor position
52 | //TODO add Javadoc
53 | //TODO Delete Done button, add back button to left side of toolbar
54 | //TODO Add Background function to note edit, then display this background on ListView
55 | //TODO Clicking on "New note" on note edit activity changes note title
56 | //TODO Default note title system (handle blank text notes, with pictures on it)
57 | //TODO Toggle panels icons color
58 | //TODO Disable text/draw panel when back button is clicked. Prevents user from saving note when tries to close panel with back button
59 |
60 | // Draw mode booleans
61 | private boolean isDrawModeOn;
62 | private boolean isTextModeOn;
63 |
64 | // Drawing canvas
65 | private DrawingView drawingView;
66 |
67 | // Brush sizes
68 | private static final float
69 | SMALL_BRUSH = 5,
70 | MEDIUM_BRUSH = 10,
71 | LARGE_BRUSH = 20;
72 |
73 | // Request code for voice input
74 | private static final int REQUEST_CODE = 1234;
75 |
76 | // Database Handler
77 | private DatabaseHandler dbHandler;
78 |
79 | // Percent of total layout height that is prepared for format text panel
80 | // Default 0.3, Values 0 < x < 1
81 | private static final double MENU_MARGIN_RELATIVE_MODIFIER = 0.3;
82 |
83 | // format text and draw panel container
84 | private LinearLayout mSliderLayout;
85 | private LinearLayout mDrawLayout;
86 |
87 | // Actual Note ID
88 | // (is -1 when it's new note)
89 | private int noteID;
90 |
91 | // Title of note
92 | private EditText noteTitle;
93 |
94 | // EditText panel
95 | private EditText editText;
96 |
97 | // Spannable used to format text
98 | // Converted to HTML String in database
99 | private Spannable spannable;
100 |
101 | // Alert dialog for back button and save button
102 | private AlertDialog alertDialogSaveNote;
103 |
104 |
105 | @Override
106 | protected void onCreate(Bundle savedInstanceState) {
107 | super.onCreate(savedInstanceState);
108 | setContentView(R.layout.activity_note);
109 |
110 | // Set Views fields values
111 | noteTitle = (EditText) findViewById(R.id.activity_note_title);
112 | editText = (EditText) findViewById(R.id.editText);
113 | mSliderLayout = (LinearLayout) findViewById(R.id.formatTextSlider);
114 | mDrawLayout = (LinearLayout) findViewById(R.id.drawPanelSlider);
115 | drawingView = (DrawingView) findViewById(R.id.drawing);
116 |
117 | // set boolean values
118 | isDrawModeOn = false;
119 | isTextModeOn = true;
120 |
121 | // Get params for format text panel and draw panel
122 | ViewGroup.LayoutParams paramsTextFormat = mSliderLayout.getLayoutParams();
123 | paramsTextFormat.height = calculateMenuMargin();
124 | ViewGroup.LayoutParams paramsDrawPanel = mDrawLayout.getLayoutParams();
125 | paramsDrawPanel.height = calculateMenuMargin();
126 |
127 | // Create DatabaseHandler
128 | dbHandler = new DatabaseHandler(getApplicationContext());
129 |
130 | // Get default spannable value
131 | spannable = editText.getText();
132 |
133 | // Setup AlertDialog
134 | alertDialogSaveNote = initAlertDialogSaveNote();
135 |
136 | // get ID data from intent
137 | Intent intent = getIntent();
138 | noteID = Integer.parseInt(intent.getStringExtra("id"));
139 |
140 | // disable soft keyboard when editText is focused
141 | disableSoftInputFromAppearing(editText);
142 |
143 | // Auto-enable format menu panel when text is selected
144 | manageContextMenuBar(editText);
145 |
146 | // Feature Disabled
147 | // Auto-enable soft keyboard when activity starts
148 | //toggleKeyboard(null);
149 |
150 | // Load note
151 | if (noteID != -1) {
152 | loadNote(noteID);
153 | }
154 |
155 | // Handling drawingView's onTouchListener via EditText onTouchListener
156 | editText.setOnTouchListener(new View.OnTouchListener() {
157 |
158 | @Override
159 | public boolean onTouch(View v, MotionEvent event) {
160 | if (isDrawModeOn) {
161 | drawingView.draw(event.getX() + editText.getX(), event.getY() + editText.getY(), event.getAction());
162 | return true;
163 | } else {
164 | return false;
165 | }
166 | }
167 | });
168 | }
169 |
170 | @Override
171 | public boolean onCreateOptionsMenu(Menu menu) {
172 | // Creating menu
173 | getMenuInflater().inflate(R.menu.menu_note, menu);
174 | return true;
175 | }
176 |
177 | /**
178 | * Method used for first setup of done button AlertDialog
179 | */
180 | private AlertDialog initAlertDialogSaveNote() {
181 |
182 | AlertDialog.Builder builder = new AlertDialog.Builder(this);
183 | builder.setTitle(this.getString(R.string.save_note_title)).setMessage(this.getString(R.string.save_note_confirmation));
184 |
185 | builder.setPositiveButton(this.getString(R.string.ok_button), new DialogInterface.OnClickListener() {
186 | public void onClick(DialogInterface dialog, int id) {
187 | finish();
188 | }
189 | });
190 | builder.setNegativeButton(this.getString(R.string.cancel_button), new DialogInterface.OnClickListener() {
191 | public void onClick(DialogInterface dialog, int id) {
192 | // Nothing happens here...
193 | }
194 | });
195 | return builder.create();
196 | }
197 |
198 | /**
199 | * Method that Overrides back button behavior
200 | */
201 | @Override
202 | public void onBackPressed() {
203 |
204 | View formatTextSliderView = findViewById(R.id.formatTextSlider);
205 | View drawPanelSliderView = findViewById(R.id.drawPanelSlider);
206 |
207 | if (formatTextSliderView.getVisibility() == View.VISIBLE) {
208 | formatTextSliderView.setVisibility(View.GONE);
209 | }
210 | else if (drawPanelSliderView.getVisibility() == View.VISIBLE) {
211 | drawPanelSliderView.setVisibility(View.GONE);
212 | }
213 | else {
214 | saveOrUpdateNote(null);
215 | }
216 | }
217 |
218 | /**
219 | * Method used to toggle format text panel
220 | *
221 | * @param item MenuItem that handles that method in .xml android:OnClick
222 | */
223 | public void toggleTextFormatMenu(@Nullable MenuItem item) {
224 |
225 | View formatTextSliderView = findViewById(R.id.formatTextSlider);
226 | View drawPanelSliderView = findViewById(R.id.drawPanelSlider);
227 |
228 | if (formatTextSliderView.getVisibility() == View.VISIBLE) {
229 | formatTextSliderView.setVisibility(View.GONE);
230 | } else {
231 | if (drawPanelSliderView.getVisibility() == View.VISIBLE) {
232 | drawPanelSliderView.setVisibility(View.GONE);
233 | }
234 | formatTextSliderView.setVisibility(View.VISIBLE);
235 | }
236 |
237 | // After changes:
238 | setDrawModeOn(formatTextSliderView.getVisibility() != View.VISIBLE
239 | && drawPanelSliderView.getVisibility() == View.VISIBLE);
240 | }
241 |
242 | /**
243 | * Method used to toggle draw menu panel
244 | *
245 | * @param item MenuItem that handles that method in .xml android:OnClick
246 | */
247 | public void toggleDrawMenu(@Nullable MenuItem item) {
248 |
249 | View formatTextSliderView = findViewById(R.id.formatTextSlider);
250 | View drawPanelSliderView = findViewById(R.id.drawPanelSlider);
251 |
252 | if (drawPanelSliderView.getVisibility() == View.VISIBLE) {
253 | drawPanelSliderView.setVisibility(View.GONE);
254 | } else {
255 | if (formatTextSliderView.getVisibility() == View.VISIBLE) {
256 | formatTextSliderView.setVisibility(View.GONE);
257 | }
258 | hideSoftKeyboard();
259 | drawPanelSliderView.setVisibility(View.VISIBLE);
260 | }
261 |
262 | // After changes:
263 | setDrawModeOn(drawPanelSliderView.getVisibility() == View.VISIBLE);
264 | }
265 |
266 | /**
267 | * Method used to set draw mode on
268 | * Draw mode is relative to text mode (may be useful in later upates)
269 | */
270 | private void setDrawModeOn(boolean isOn) {
271 | isDrawModeOn = isOn;
272 | isTextModeOn = !isOn;
273 | }
274 |
275 |
276 | /**
277 | * Method that calculates space left for EditText when format text panel is Visible
278 | *
279 | * @return Screen independent pixel count of space for EditText
280 | */
281 | private int calculateMenuMargin() {
282 | WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
283 | Display display = wm.getDefaultDisplay();
284 | Point size = new Point();
285 | display.getSize(size);
286 | int height = size.y;
287 | return (int) Math.round(height * MENU_MARGIN_RELATIVE_MODIFIER);
288 | }
289 |
290 | /**
291 | * Method used to toggle soft keyboard
292 | *
293 | * @param item MenuItem that handles that method in .xml android:OnClick
294 | */
295 | public void toggleKeyboard(@Nullable MenuItem item) {
296 | InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
297 | imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
298 | if (findViewById(R.id.drawPanelSlider).getVisibility() == View.VISIBLE) {
299 | findViewById(R.id.drawPanelSlider).setVisibility(View.GONE);
300 | }
301 | }
302 |
303 | /**
304 | * Method used to hide keyboard
305 | */
306 | private void hideSoftKeyboard() {
307 | if (this.getCurrentFocus() != null) {
308 | try {
309 | InputMethodManager imm = (InputMethodManager) this.getSystemService(Context.INPUT_METHOD_SERVICE);
310 | imm.hideSoftInputFromWindow(this.getCurrentFocus().getApplicationWindowToken(), 0);
311 | } catch (RuntimeException e) {
312 | //ignore
313 | }
314 | }
315 | }
316 |
317 | /**
318 | * Method that prevents soft keyboard appear when EditText is focused
319 | *
320 | * @param editText EditText to apply changes to
321 | */
322 | private static void disableSoftInputFromAppearing(EditText editText) {
323 | if (Build.VERSION.SDK_INT >= 11) { //TODO: remove
324 | editText.setRawInputType(InputType.TYPE_CLASS_TEXT);
325 | editText.setTextIsSelectable(true);
326 | } else {
327 | editText.setRawInputType(InputType.TYPE_NULL);
328 | editText.setFocusable(true);
329 | }
330 | }
331 |
332 | /**
333 | * Method used to show format text panel when context menu is ON
334 | * i.e. When text is selected
335 | *
336 | * @param editText EditText to apply changes to
337 | */
338 | private void manageContextMenuBar(EditText editText) {
339 |
340 | editText.setCustomSelectionActionModeCallback(new ActionMode.Callback() {
341 |
342 | public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
343 | return true;
344 | }
345 |
346 | public void onDestroyActionMode(ActionMode mode) {
347 | if (findViewById(R.id.formatTextSlider).getVisibility() == View.VISIBLE) {
348 | findViewById(R.id.formatTextSlider).setVisibility(View.GONE);
349 | }
350 | }
351 |
352 | public boolean onCreateActionMode(ActionMode mode, Menu menu) {
353 |
354 | if (findViewById(R.id.formatTextSlider).getVisibility() == View.GONE) {
355 | findViewById(R.id.formatTextSlider).setVisibility(View.VISIBLE);
356 | }
357 | return true;
358 | }
359 |
360 | public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
361 | return false;
362 | }
363 | });
364 | }
365 |
366 | /**
367 | * Method used to format selected text by modifying Spannable object
368 | *
369 | * @param view that handles that method in .xml android:OnClick
370 | */
371 | public void formatTextActionPerformed(View view) {
372 |
373 | EditText editTextLocal = (EditText) findViewById(R.id.editText);
374 | spannable = editTextLocal.getText();
375 |
376 | int posStart = editTextLocal.getSelectionStart();
377 | int posEnd = editTextLocal.getSelectionEnd();
378 |
379 | if (view.getTag().toString().equals("bold")) {
380 | spannable.setSpan(new StyleSpan(Typeface.BOLD), posStart, posEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
381 | } else if (view.getTag().toString().equals("italic")) {
382 | spannable.setSpan(new StyleSpan(Typeface.ITALIC), posStart, posEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
383 | } else if (view.getTag().toString().equals("underline")) {
384 | spannable.setSpan(new UnderlineSpan(), posStart, posEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
385 | } else if (view.getTag().toString().equals("textBlack")) {
386 | spannable.setSpan(new ForegroundColorSpan(Color.BLACK), posStart, posEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
387 | } else if (view.getTag().toString().equals("textRed")) {
388 | spannable.setSpan(new ForegroundColorSpan(Color.RED), posStart, posEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
389 | } else if (view.getTag().toString().equals("textBlue")) {
390 | spannable.setSpan(new ForegroundColorSpan(Color.BLUE), posStart, posEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
391 | } else if (view.getTag().toString().equals("textGreen")) {
392 | spannable.setSpan(new ForegroundColorSpan(Color.GREEN), posStart, posEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
393 | } else if (view.getTag().toString().equals("textYellow")) {
394 | spannable.setSpan(new ForegroundColorSpan(Color.YELLOW), posStart, posEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
395 | }
396 | editTextLocal.setText(spannable);
397 | }
398 |
399 | /**
400 | * Method used to add note text to EditText
401 | *
402 | * @param noteID ID number of the Note entry in the SQLite database
403 | */
404 | private void loadNote(int noteID) {
405 |
406 | try {
407 | Note n = dbHandler.getNote(noteID);
408 | //todo fix
409 | editText.setText(n.getSpannable());
410 | editText.setSelection(editText.getText().toString().length());
411 | noteTitle.setText(n.getTitle());
412 | drawingView.setBitmap(n.getImage());
413 | }catch (SQLiteException e){
414 | e.printStackTrace();
415 | }
416 | }
417 |
418 | /**
419 | * Method used for Saving/Updating/Deleting note with special conditions
420 | * Handled by "Done button"
421 | */
422 | public void saveOrUpdateNote(@Nullable MenuItem menu) {
423 |
424 | spannable = editText.getText();
425 | String title = noteTitle.getText().toString();
426 |
427 | Note note = new Note();
428 |
429 | note.setTitle(title);
430 | note.setSpannable(spannable);
431 | note.setImage(drawingView.getCanvasBitmap());
432 | note.setDateUpdated(new Date());
433 |
434 | if (noteID != -1) {
435 | note.setId(noteID);
436 | }
437 |
438 | new SaveOrUpdateNoteTask(this).execute(note);
439 |
440 | hideSoftKeyboard();
441 | finish();
442 | }
443 |
444 | /**
445 | * Handle voice button click
446 | */
447 | public void speakButtonClicked(MenuItem menuItem) {
448 | startVoiceRecognitionActivity();
449 | }
450 |
451 | /**
452 | * Start the voice recognition activity.
453 | */
454 | private void startVoiceRecognitionActivity() {
455 | Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
456 | intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
457 | RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
458 | intent.putExtra(RecognizerIntent.EXTRA_PROMPT, R.string.voice_hint);
459 | startActivityForResult(intent, REQUEST_CODE);
460 | }
461 |
462 | /**
463 | * Handle the results from the voice recognition
464 | */
465 | @Override
466 | protected void onActivityResult(int requestCode, int resultCode, Intent data) {
467 | if (requestCode == REQUEST_CODE && resultCode == RESULT_OK) {
468 | ArrayList matches = data.getStringArrayListExtra(
469 | RecognizerIntent.EXTRA_RESULTS);
470 |
471 | if (matches.size() > 0) {
472 | if (editText.getText().toString().length() == 0) {
473 | editText.setText(matches.get(0));
474 | editText.setSelection(editText.getText().toString().length());
475 | } else {
476 | Spanned spanText = (SpannedString) TextUtils.concat(editText.getText(), " " + matches.get(0));
477 | editText.setText(spanText);
478 | editText.setSelection(editText.getText().toString().length());
479 | }
480 | }
481 | }
482 | super.onActivityResult(requestCode, resultCode, data);
483 | }
484 |
485 | /**
486 | * Method used to change drawing color
487 | */
488 | public void changeColor(View v) {
489 |
490 | if (v.getTag().toString().equals("black")) {
491 | drawingView.setPaintColor(Color.BLACK);
492 | } else if (v.getTag().toString().equals("red")) {
493 | drawingView.setPaintColor(Color.RED);
494 | } else if (v.getTag().toString().equals("blue")) {
495 | drawingView.setPaintColor(Color.BLUE);
496 | } else if (v.getTag().toString().equals("green")) {
497 | drawingView.setPaintColor(Color.GREEN);
498 | } else if (v.getTag().toString().equals("yellow")) {
499 | drawingView.setPaintColor(Color.YELLOW);
500 | }
501 | }
502 |
503 | /**
504 | * Method used to change brush size
505 | */
506 | public void changeBrushSize(View v) {
507 |
508 | if (v.getTag().toString().equals("small")) {
509 | drawingView.setBrushSize(SMALL_BRUSH);
510 | } else if (v.getTag().toString().equals("medium")) {
511 | drawingView.setBrushSize(MEDIUM_BRUSH);
512 | } else if (v.getTag().toString().equals("large")) {
513 | drawingView.setBrushSize(LARGE_BRUSH);
514 | }
515 | }
516 |
517 | /**
518 | * Method used to change erase mode
519 | * Handled by erase and paint button
520 | */
521 | public void eraseOrPaintMode(View v) {
522 | drawingView.setErase(v.getTag().toString().equals("erase"));
523 | }
524 |
525 | public void wipeCanvas(View v) {
526 | drawingView.startNew();
527 | }
528 | }
529 |
--------------------------------------------------------------------------------