Skip to content

0. Mask

Egor Taflanidi edited this page Feb 6, 2019 · 3 revisions

Mask is a central class responsible for formatting the input, producing the output, and extracting the valuable characters.

class Mask(format: String, private val customNotations: List<Notation>) {
    data class Result(
        val formattedText: CaretString,
        val extractedValue: String,
        val affinity: Int,
        val complete: Boolean
    )

    constructor(format: String): this(format, emptyList())

    companion object Factory {
        fun getOrCreate(format: String, customNotations: List<Notation>): Mask

        fun isValid(format: String, customNotations: List<Notation>): Boolean
    }

    fun apply(text: CaretString, autocomplete: Boolean): Result

    fun placeholder():           String
    fun acceptableTextLength():  Int
    fun totalTextLength():       Int
    fun acceptableValueLength(): Int
    fun totalValueLength():      Int
}

Initialisation

Mask object is a state machine with its own internal graph of states to move through. The graph is compiled from the format during the initialisation. If the format is invalid, compiler throws an exception.

Mask(format: String, private val customNotations: List<Notation>)

— constructor passes the list of custom notations and the format to the internal compiler.

fun Factory::getOrCreate(format: String, customNotations: List<Notation>): Mask

— in order to avoid graph re-compilation overhead each time you make a Mask object, use the getOrCreate() class method — it has its own cache from where previously created Mask objects with similar graphs are fetched instead of being created.

fun Factory::isValid(format: String, customNotations: List<Notation>): Boolean

— is a convenience method to check whether or not this particular format will cause a compilation exception given the list of custom notations.

Applying the format

fun apply(text: CaretString, autocomplete: Boolean): Result

— you may use this method as a «headless» approach to format some text somewhere in your application's code without involving a View.

CaretString is a structure representing a string and a caret (cursor) position inside of it.

data class CaretString(val string: String, val caretPosition: Int)

Adding and removing characters leads to the cursor movements. For instance, if the input string contains unwanted symbols, they are removed, and the cursor moves left:

Mask:    [000]

Input:   1a2
           ^
Output:  12
          ^

autocomplete flag

Autocompletion allows automatic insertion of constant characters (see constant blocks and separators).

For instance, having a MM/YY date field, / symbol would require a full keyboard, but you can actually get away with a numeric one:

[00]{/}[00]
Key pressed   Output

1             1
2             12/
3             12/3
4             12/34

Without the autocompletion, the picture is a bit different:

Key pressed   Output

1             1
2             12
3             12/3
4             12/34

Enabled autocompletion essentially helps user to understand that he doesn't need to type the dividing / by his hand, which makes data input more clear.

Result

The resulting cursor position along with the output (formatted text), value completeness and calculated affinity are returned as a Mask.Result object:

data class Result(
    val formattedText: CaretString,
    val extractedValue: String,
    val affinity: Int,
    val complete: Boolean
)

affinity is an integer value representing the similarity between the input and the mask pattern. This value is necessary to determine the most suitable mask.

complete flag shows if the extracted value contains all the mandatory characters.

Properties and metrics

Each mask has its metrics.

  • acceptableTextLength is the minimum length the output has to be in order to be acceptable (complete == true);
  • totalTextLength is the maximum output length, with all optional characters included;
  • acceptableValueLength is the minimum acceptable extracted value length;
  • totalValueLength is the maximum extracted value length.

placeholder produces a simple placeholder text that can serve as a text field hint (including optional symbols; a for arbitrary letters, 0 for arbitrary digits, - for arbitrary alphanumerics):

([009])[Aa] ~> (000)aa
Clone this wiki locally