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) {
R.id.open_note -> displayOpenNoteDialog()
R.id.save_note -> saveNote()
R.id.undo -> undo()
R.id.redo -> redo()
R.id.new_note -> displayNewNoteDialog()
R.id.rename_note -> displayRenameDialog()
R.id.share -> shareText()
@ -287,11 +289,11 @@ class MainActivity : SimpleActivity(), ViewPager.OnPageChangeListener {
private fun openFile() {
FilePickerDialog(this) {
openFile(it, true, {
openFile(it, true) {
OpenFileDialog(this, it.path) {
addNewNote(it)
}
})
}
}
}
@ -524,6 +526,14 @@ class MainActivity : SimpleActivity(), ViewPager.OnPageChangeListener {
invalidateOptionsMenu()
}
private fun undo() {
mAdapter?.undo(view_pager.currentItem)
}
private fun redo() {
mAdapter?.redo(view_pager.currentItem)
}
private fun getNoteIndexWithId(id: Int): Int {
for (i in 0 until mNotes.count()) {
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 undo(position: Int) = fragments[position]?.undo()
fun redo(position: Int) = fragments[position]?.redo()
override fun finishUpdate(container: ViewGroup) {
try {
super.finishUpdate(container)

View File

@ -4,7 +4,9 @@ import android.graphics.Typeface
import android.os.Bundle
import android.support.v4.app.Fragment
import android.text.Editable
import android.text.Selection
import android.text.TextWatcher
import android.text.style.UnderlineSpan
import android.text.util.Linkify
import android.util.TypedValue
import android.view.Gravity
@ -22,12 +24,18 @@ import com.simplemobiletools.notes.extensions.getTextSize
import com.simplemobiletools.notes.extensions.updateWidget
import com.simplemobiletools.notes.helpers.*
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.view.*
import kotlinx.android.synthetic.main.note_view_horiz_scrollable.view.*
import java.io.File
// text history handling taken from https://gist.github.com/zeleven/0cfa738c1e8b65b23ff7df1fc30c9f7e
class NoteFragment : Fragment() {
private var textHistory = TextHistory()
private var isUndoOrRedo = false
private var noteId = 0
lateinit var note: Note
lateinit var view: ViewGroup
@ -161,11 +169,69 @@ class NoteFragment : Fragment() {
notes_counter.text = words.count { it.isNotEmpty() }.toString()
}
private var textWatcher: TextWatcher = object : TextWatcher {
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {
fun undo() {
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) {

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?)