blob: 46db63b13fb72e7c7f111bede235e6ecf3204eb5 [file] [log] [blame]
/*
* Copyright 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.wear.watchface
import android.util.Printer
import java.io.PrintWriter
import java.io.Writer
/**
* Lightweight wrapper around [java.io.PrintWriter] that automatically indents newlines based
* on internal state.
*
* Delays writing indent until first actual write on a newline, enabling indent modification after
* newline.
*/
internal class IndentingPrintWriter(
writer: Writer,
private val singleIndent: String = "\t"
) : Printer {
internal val writer: PrintWriter = PrintWriter(writer)
/** Mutable version of current indent */
private val indentBuilder = StringBuilder()
/** Cache of current [indentBuilder] value */
private var currentIndent: CharArray? = null
/**
* Flag indicating if we're currently sitting on an empty line, and that next write should be
* prefixed with the current indent.
*/
private var emptyLine = true
/** Increases the indentation level for future lines. */
fun increaseIndent() {
indentBuilder.append(singleIndent)
currentIndent = null
}
/** Decreases the indentation level for future lines. */
fun decreaseIndent() {
indentBuilder.delete(0, singleIndent.length)
currentIndent = null
}
/** Prints `string`, followed by a newline. */
// Printer
override fun println(string: String) {
print(string)
print("\n")
}
/** Prints `string`, or `"null"` */
fun print(string: String?) {
val str = string ?: "null"
write(str, 0, str.length)
}
/** Ensures that all pending data is sent out to the target */
fun flush() {
writer.flush()
}
private fun write(string: String, offset: Int, count: Int) {
val bufferEnd = offset + count
var lineStart = offset
var lineEnd = offset
// March through incoming buffer looking for newlines
while (lineEnd < bufferEnd) {
val ch = string[lineEnd++]
if (ch == '\n') {
maybeWriteIndent()
writer.write(string, lineStart, lineEnd - lineStart)
lineStart = lineEnd
emptyLine = true
}
}
if (lineStart != lineEnd) {
maybeWriteIndent()
writer.write(string, lineStart, lineEnd - lineStart)
}
}
private fun maybeWriteIndent() {
if (emptyLine) {
emptyLine = false
if (indentBuilder.isNotEmpty()) {
if (currentIndent == null) {
currentIndent = indentBuilder.toString().toCharArray()
}
writer.write(currentIndent, 0, currentIndent!!.size)
}
}
}
}