mirror of
https://github.com/SimpleMobileTools/Simple-Notes.git
synced 2025-02-10 00:10:48 +01:00
adding the undo/redo functionality
This commit is contained in:
parent
48f31b8d83
commit
2c3a6937a7
@ -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) {
|
||||||
|
@ -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)
|
||||||
|
@ -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) {
|
||||||
|
@ -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++
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
package com.simplemobiletools.notes.models
|
||||||
|
|
||||||
|
data class TextHistoryItem(val start: Int, val before: CharSequence?, val after: CharSequence?)
|
Loading…
x
Reference in New Issue
Block a user