adding the undo/redo functionality

This commit is contained in:
tibbi 2018-07-17 21:09:53 +02:00
parent 48f31b8d83
commit 2c3a6937a7
5 changed files with 123 additions and 5 deletions

View File

@ -132,6 +132,8 @@ class MainActivity : SimpleActivity(), ViewPager.OnPageChangeListener {
when (item.itemId) { when (item.itemId) {
R.id.open_note -> displayOpenNoteDialog() R.id.open_note -> displayOpenNoteDialog()
R.id.save_note -> saveNote() R.id.save_note -> saveNote()
R.id.undo -> undo()
R.id.redo -> redo()
R.id.new_note -> displayNewNoteDialog() R.id.new_note -> displayNewNoteDialog()
R.id.rename_note -> displayRenameDialog() R.id.rename_note -> displayRenameDialog()
R.id.share -> shareText() R.id.share -> shareText()
@ -287,11 +289,11 @@ class MainActivity : SimpleActivity(), ViewPager.OnPageChangeListener {
private fun openFile() { private fun openFile() {
FilePickerDialog(this) { FilePickerDialog(this) {
openFile(it, true, { openFile(it, true) {
OpenFileDialog(this, it.path) { OpenFileDialog(this, it.path) {
addNewNote(it) addNewNote(it)
} }
}) }
} }
} }
@ -524,6 +526,14 @@ class MainActivity : SimpleActivity(), ViewPager.OnPageChangeListener {
invalidateOptionsMenu() invalidateOptionsMenu()
} }
private fun undo() {
mAdapter?.undo(view_pager.currentItem)
}
private fun redo() {
mAdapter?.redo(view_pager.currentItem)
}
private fun getNoteIndexWithId(id: Int): Int { private fun getNoteIndexWithId(id: Int): Int {
for (i in 0 until mNotes.count()) { for (i in 0 until mNotes.count()) {
if (mNotes[i].id == id) { if (mNotes[i].id == id) {

View File

@ -42,6 +42,10 @@ class NotesPagerAdapter(fm: FragmentManager, val notes: List<Note>, val activity
fun focusEditText(position: Int) = fragments[position]?.focusEditText() fun focusEditText(position: Int) = fragments[position]?.focusEditText()
fun undo(position: Int) = fragments[position]?.undo()
fun redo(position: Int) = fragments[position]?.redo()
override fun finishUpdate(container: ViewGroup) { override fun finishUpdate(container: ViewGroup) {
try { try {
super.finishUpdate(container) super.finishUpdate(container)

View File

@ -4,7 +4,9 @@ import android.graphics.Typeface
import android.os.Bundle import android.os.Bundle
import android.support.v4.app.Fragment import android.support.v4.app.Fragment
import android.text.Editable import android.text.Editable
import android.text.Selection
import android.text.TextWatcher import android.text.TextWatcher
import android.text.style.UnderlineSpan
import android.text.util.Linkify import android.text.util.Linkify
import android.util.TypedValue import android.util.TypedValue
import android.view.Gravity import android.view.Gravity
@ -22,12 +24,18 @@ import com.simplemobiletools.notes.extensions.getTextSize
import com.simplemobiletools.notes.extensions.updateWidget import com.simplemobiletools.notes.extensions.updateWidget
import com.simplemobiletools.notes.helpers.* import com.simplemobiletools.notes.helpers.*
import com.simplemobiletools.notes.models.Note import com.simplemobiletools.notes.models.Note
import com.simplemobiletools.notes.models.TextHistory
import com.simplemobiletools.notes.models.TextHistoryItem
import kotlinx.android.synthetic.main.fragment_note.* import kotlinx.android.synthetic.main.fragment_note.*
import kotlinx.android.synthetic.main.fragment_note.view.* import kotlinx.android.synthetic.main.fragment_note.view.*
import kotlinx.android.synthetic.main.note_view_horiz_scrollable.view.* import kotlinx.android.synthetic.main.note_view_horiz_scrollable.view.*
import java.io.File import java.io.File
// text history handling taken from https://gist.github.com/zeleven/0cfa738c1e8b65b23ff7df1fc30c9f7e
class NoteFragment : Fragment() { class NoteFragment : Fragment() {
private var textHistory = TextHistory()
private var isUndoOrRedo = false
private var noteId = 0 private var noteId = 0
lateinit var note: Note lateinit var note: Note
lateinit var view: ViewGroup lateinit var view: ViewGroup
@ -161,11 +169,69 @@ class NoteFragment : Fragment() {
notes_counter.text = words.count { it.isNotEmpty() }.toString() notes_counter.text = words.count { it.isNotEmpty() }.toString()
} }
private var textWatcher: TextWatcher = object : TextWatcher { fun undo() {
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { val edit = textHistory.getPrevious() ?: return
val text = view.notes_view.editableText
val start = edit.start
val end = start + if (edit.after != null) edit.after.length else 0
isUndoOrRedo = true
text.replace(start, end, edit.before)
isUndoOrRedo = false
for (span in text.getSpans(0, text.length, UnderlineSpan::class.java)) {
text.removeSpan(span)
} }
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) { Selection.setSelection(text, if (edit.before == null) {
start
} else {
start + edit.before.length
})
}
fun redo() {
val edit = textHistory.getNext() ?: return
val text = view.notes_view.editableText
val start = edit.start
val end = start + if (edit.before != null) edit.before.length else 0
isUndoOrRedo = true
text.replace(start, end, edit.after)
isUndoOrRedo = false
for (o in text.getSpans(0, text.length, UnderlineSpan::class.java)) {
text.removeSpan(o)
}
Selection.setSelection(text, if (edit.after == null) {
start
} else {
start + edit.after.length
})
}
fun isUndoAvailable() = textHistory.position > 0
fun isRedoAvailable() = textHistory.position < textHistory.history.size
private var textWatcher: TextWatcher = object : TextWatcher {
private var beforeChange: CharSequence? = null
private var afterChange: CharSequence? = null
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {
if (!isUndoOrRedo) {
beforeChange = s.subSequence(start, start + count)
}
}
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
if (!isUndoOrRedo) {
afterChange = s.subSequence(start, start + count)
textHistory.add(TextHistoryItem(start, beforeChange!!, afterChange!!))
}
} }
override fun afterTextChanged(editable: Editable) { override fun afterTextChanged(editable: Editable) {

View File

@ -0,0 +1,35 @@
package com.simplemobiletools.notes.models
import java.util.*
class TextHistory {
var position = 0
val history = LinkedList<TextHistoryItem>()
fun getPrevious(): TextHistoryItem? {
if (position == 0) {
return null
}
position--
return history[position]
}
fun getNext(): TextHistoryItem? {
if (position >= history.size) {
return null
}
val item = history[position]
position++
return item
}
fun add(item: TextHistoryItem) {
while (history.size > position) {
history.removeLast()
}
history.add(item)
position++
}
}

View File

@ -0,0 +1,3 @@
package com.simplemobiletools.notes.models
data class TextHistoryItem(val start: Int, val before: CharSequence?, val after: CharSequence?)