<commit_before>package me.daemon.adaptivelabel

import android.annotation.TargetApi
import android.content.Context
import android.os.Build
import android.util.AttributeSet
import android.view.View
import android.view.ViewDebug
import android.view.ViewGroup
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
import me.daemon.library.R

/**
 * 自适应标签容器
 *
 * @author daemon
 * @since 2016-11-08 00:00
 */
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
class AdaptiveLabelGroup @JvmOverloads constructor(
        context: Context,
        attrs: AttributeSet? = null,
        defStyleAttr: Int = 0,
        defStyleRes: Int = 0
) : ViewGroup(context, attrs, defStyleAttr, defStyleRes) {

    /**
     * 水平间距
     */
    @ViewDebug.ExportedProperty(category = "layout")
    var horizontalDividerSize = 0
        /**
         * 设置水平间距
         *
         * @param horizontalDividerSize 水平间距
         */
        set(horizontalDividerSize) {
            if (field != horizontalDividerSize) {
                field = horizontalDividerSize
                requestLayout()
                invalidate()
            }
        }

    /**
     * 垂直间距
     */
    @ViewDebug.ExportedProperty(category = "layout")
    var verticalDividerSize = 0
        /**
         * 设置垂直间距
         *
         * @param verticalDividerSize 垂直间距
         */
        set(verticalDividerSize) {
            if (field != verticalDividerSize) {
                field = verticalDividerSize
                requestLayout()
                invalidate()
            }
        }

    /**
     * 最大行数，默认为0不限制行数
     */
    @ViewDebug.ExportedProperty(category = "layout")
    var maxRows = 0
        /**
         * 设置最大行数
         *
         * @param maxRows 最大行数，默认为0，为0不限制行数
         */
        set(maxRows) {
            if (maxRows < 0) {
                throw IllegalArgumentException("maxRows can't be negative")
            }

            if (field != maxRows) {
                field = maxRows
                requestLayout()
                invalidate()
            }
        }

    init {
        if (null != attrs) {
            val a = context.obtainStyledAttributes(
                    attrs, R.styleable.AdaptiveLabelGroup, defStyleAttr, defStyleRes)

            horizontalDividerSize = a.getDimension(R.styleable.AdaptiveLabelGroup_horizontal_divider_size, 0f).toInt()
            verticalDividerSize = a.getDimension(R.styleable.AdaptiveLabelGroup_vertical_divider_size, 0f).toInt()
            maxRows = a.getInt(R.styleable.AdaptiveLabelGroup_max_rows, 0)

            a.recycle()
        }
    }

    override fun generateLayoutParams(attrs: AttributeSet): ViewGroup.LayoutParams {
        return LayoutParams(context, attrs)
    }

    override fun generateLayoutParams(lp: ViewGroup.LayoutParams): ViewGroup.LayoutParams {
        return (lp as? LayoutParams)?.let { LayoutParams(it) }
                ?: ((lp as? ViewGroup.MarginLayoutParams)?.let { LayoutParams(it) }
                        ?: LayoutParams(lp))
    }

    override fun generateDefaultLayoutParams(): ViewGroup.LayoutParams {
        return LayoutParams(WRAP_CONTENT, WRAP_CONTENT)
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        val count = childCount

        val widthSpecSize = View.MeasureSpec.getSize(widthMeasureSpec)

        val heightSpecMode = View.MeasureSpec.getMode(heightMeasureSpec)
        val heightSpecSize = View.MeasureSpec.getSize(heightMeasureSpec)

        for (i in 0 until count) {
            val v = getChildAt(i)
            if (v.visibility != View.GONE) {
                measureChildWithMargins(v, widthMeasureSpec, 0, heightMeasureSpec, 0)
            }
        }

        // 当前总高度
        var totalHeight: Int

        if (View.MeasureSpec.EXACTLY == heightSpecMode) {
            totalHeight = heightSpecSize
        } else {

            // 一行View总宽度，初始为容器左padding
            var width = paddingLeft

            // 当前行高度，以该行View中高度最高的为准
            var rowHeight = 0

            // 总高度初始加上容器顶部padding
            totalHeight = paddingTop

            // 行数
            var row = 0

            for (i in 0 until count) {
                val v = getChildAt(i)

                if (v.visibility != View.GONE) {
                    val lp = v.layoutParams as LayoutParams
                    val childW = v.measuredWidth
                    val childH = v.measuredHeight

                    if (width + childW + lp.leftMargin + lp.rightMargin + paddingRight > widthSpecSize) {
                        // 总宽度超过容器宽度，总高度加上垂直间距及当前行高度，换行，重置行高、行宽
                        totalHeight += this.verticalDividerSize + rowHeight
                        rowHeight = 0
                        width = paddingLeft
                        row++

                        if (this.maxRows > 0 && row == this.maxRows) {
                            // 最大行数非0时，超过最大行数不显示
                            break
                        }
                    }

                    // 行宽加上垂直间距、当前View宽度及左右margin
                    width += this.horizontalDividerSize + childW + lp.leftMargin + lp.rightMargin

                    if (rowHeight < childH + lp.topMargin + lp.bottomMargin) {
                        // 行高取当前行中View高度+上下margin最大值
                        rowHeight = childH + lp.topMargin + lp.bottomMargin
                    }
                }
            }

            // 计算完成，总高度加上最后一行的高度
            totalHeight += rowHeight

            // 总高度加上容器底部padding
            totalHeight += paddingBottom
        }

        setMeasuredDimension(widthSpecSize, totalHeight)
    }

    override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
        val count = childCount

        var width = paddingLeft

        var rowHeight = 0

        var totalHeight = paddingTop

        val measuredWidth = measuredWidth

        var row = 0

        for (i in 0 until count) {
            val v = getChildAt(i)

            if (v.visibility != View.GONE) {
                val lp = v.layoutParams as LayoutParams
                val childW = v.measuredWidth
                val childH = v.measuredHeight

                if (width + childW + lp.leftMargin + lp.rightMargin + paddingRight > measuredWidth) {
                    totalHeight += this.verticalDividerSize + rowHeight
                    rowHeight = 0
                    width = paddingLeft
                    row++

                    if (this.maxRows > 0 && row == this.maxRows) {
                        break
                    }
                }

                v.layout(width + lp.leftMargin, totalHeight + lp.topMargin,
                        width + lp.leftMargin + childW, totalHeight + lp.topMargin + childH)

                width += this.horizontalDividerSize + childW + lp.leftMargin + lp.rightMargin

                if (rowHeight < childH + lp.topMargin + lp.bottomMargin) {
                    rowHeight = childH + lp.topMargin + lp.bottomMargin
                }
            }
        }
    }

    class LayoutParams : ViewGroup.MarginLayoutParams {

        constructor(c: Context, attrs: AttributeSet) : super(c, attrs)

        constructor(width: Int, height: Int) : super(width, height)

        constructor(p: ViewGroup.LayoutParams) : super(p)

        constructor(source: ViewGroup.MarginLayoutParams) : super(source)

        constructor(source: LayoutParams) : super(source)
    }
}
<commit_msg>use separate category<commit_after>package me.daemon.adaptivelabel

import android.annotation.TargetApi
import android.content.Context
import android.os.Build
import android.util.AttributeSet
import android.view.View
import android.view.ViewDebug
import android.view.ViewGroup
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
import me.daemon.library.R

/**
 * 自适应标签容器
 *
 * @author daemon
 * @since 2016-11-08 00:00
 */
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
class AdaptiveLabelGroup @JvmOverloads constructor(
        context: Context,
        attrs: AttributeSet? = null,
        defStyleAttr: Int = 0,
        defStyleRes: Int = 0
) : ViewGroup(context, attrs, defStyleAttr, defStyleRes) {

    /**
     * 水平间距
     */
    @ViewDebug.ExportedProperty(category = "daemon")
    var horizontalDividerSize = 0
        /**
         * 设置水平间距
         *
         * @param horizontalDividerSize 水平间距
         */
        set(horizontalDividerSize) {
            if (field != horizontalDividerSize) {
                field = horizontalDividerSize
                requestLayout()
                invalidate()
            }
        }

    /**
     * 垂直间距
     */
    @ViewDebug.ExportedProperty(category = "daemon")
    var verticalDividerSize = 0
        /**
         * 设置垂直间距
         *
         * @param verticalDividerSize 垂直间距
         */
        set(verticalDividerSize) {
            if (field != verticalDividerSize) {
                field = verticalDividerSize
                requestLayout()
                invalidate()
            }
        }

    /**
     * 最大行数，默认为0不限制行数
     */
    @ViewDebug.ExportedProperty(category = "daemon")
    var maxRows = 0
        /**
         * 设置最大行数
         *
         * @param maxRows 最大行数，默认为0，为0不限制行数
         */
        set(maxRows) {
            if (maxRows < 0) {
                throw IllegalArgumentException("maxRows can't be negative")
            }

            if (field != maxRows) {
                field = maxRows
                requestLayout()
                invalidate()
            }
        }

    init {
        if (null != attrs) {
            val a = context.obtainStyledAttributes(
                    attrs, R.styleable.AdaptiveLabelGroup, defStyleAttr, defStyleRes)

            horizontalDividerSize = a.getDimension(R.styleable.AdaptiveLabelGroup_horizontal_divider_size, 0f).toInt()
            verticalDividerSize = a.getDimension(R.styleable.AdaptiveLabelGroup_vertical_divider_size, 0f).toInt()
            maxRows = a.getInt(R.styleable.AdaptiveLabelGroup_max_rows, 0)

            a.recycle()
        }
    }

    override fun generateLayoutParams(attrs: AttributeSet): ViewGroup.LayoutParams {
        return LayoutParams(context, attrs)
    }

    override fun generateLayoutParams(lp: ViewGroup.LayoutParams): ViewGroup.LayoutParams {
        return (lp as? LayoutParams)?.let { LayoutParams(it) }
                ?: ((lp as? ViewGroup.MarginLayoutParams)?.let { LayoutParams(it) }
                        ?: LayoutParams(lp))
    }

    override fun generateDefaultLayoutParams(): ViewGroup.LayoutParams {
        return LayoutParams(WRAP_CONTENT, WRAP_CONTENT)
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        val count = childCount

        val widthSpecSize = View.MeasureSpec.getSize(widthMeasureSpec)

        val heightSpecMode = View.MeasureSpec.getMode(heightMeasureSpec)
        val heightSpecSize = View.MeasureSpec.getSize(heightMeasureSpec)

        for (i in 0 until count) {
            val v = getChildAt(i)
            if (v.visibility != View.GONE) {
                measureChildWithMargins(v, widthMeasureSpec, 0, heightMeasureSpec, 0)
            }
        }

        // 当前总高度
        var totalHeight: Int

        if (View.MeasureSpec.EXACTLY == heightSpecMode) {
            totalHeight = heightSpecSize
        } else {

            // 一行View总宽度，初始为容器左padding
            var width = paddingLeft

            // 当前行高度，以该行View中高度最高的为准
            var rowHeight = 0

            // 总高度初始加上容器顶部padding
            totalHeight = paddingTop

            // 行数
            var row = 0

            for (i in 0 until count) {
                val v = getChildAt(i)

                if (v.visibility != View.GONE) {
                    val lp = v.layoutParams as LayoutParams
                    val childW = v.measuredWidth
                    val childH = v.measuredHeight

                    if (width + childW + lp.leftMargin + lp.rightMargin + paddingRight > widthSpecSize) {
                        // 总宽度超过容器宽度，总高度加上垂直间距及当前行高度，换行，重置行高、行宽
                        totalHeight += this.verticalDividerSize + rowHeight
                        rowHeight = 0
                        width = paddingLeft
                        row++

                        if (this.maxRows > 0 && row == this.maxRows) {
                            // 最大行数非0时，超过最大行数不显示
                            break
                        }
                    }

                    // 行宽加上垂直间距、当前View宽度及左右margin
                    width += this.horizontalDividerSize + childW + lp.leftMargin + lp.rightMargin

                    if (rowHeight < childH + lp.topMargin + lp.bottomMargin) {
                        // 行高取当前行中View高度+上下margin最大值
                        rowHeight = childH + lp.topMargin + lp.bottomMargin
                    }
                }
            }

            // 计算完成，总高度加上最后一行的高度
            totalHeight += rowHeight

            // 总高度加上容器底部padding
            totalHeight += paddingBottom
        }

        setMeasuredDimension(widthSpecSize, totalHeight)
    }

    override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
        val count = childCount

        var width = paddingLeft

        var rowHeight = 0

        var totalHeight = paddingTop

        val measuredWidth = measuredWidth

        var row = 0

        for (i in 0 until count) {
            val v = getChildAt(i)

            if (v.visibility != View.GONE) {
                val lp = v.layoutParams as LayoutParams
                val childW = v.measuredWidth
                val childH = v.measuredHeight

                if (width + childW + lp.leftMargin + lp.rightMargin + paddingRight > measuredWidth) {
                    totalHeight += this.verticalDividerSize + rowHeight
                    rowHeight = 0
                    width = paddingLeft
                    row++

                    if (this.maxRows > 0 && row == this.maxRows) {
                        break
                    }
                }

                v.layout(width + lp.leftMargin, totalHeight + lp.topMargin,
                        width + lp.leftMargin + childW, totalHeight + lp.topMargin + childH)

                width += this.horizontalDividerSize + childW + lp.leftMargin + lp.rightMargin

                if (rowHeight < childH + lp.topMargin + lp.bottomMargin) {
                    rowHeight = childH + lp.topMargin + lp.bottomMargin
                }
            }
        }
    }

    class LayoutParams : ViewGroup.MarginLayoutParams {

        constructor(c: Context, attrs: AttributeSet) : super(c, attrs)

        constructor(width: Int, height: Int) : super(width, height)

        constructor(p: ViewGroup.LayoutParams) : super(p)

        constructor(source: ViewGroup.MarginLayoutParams) : super(source)

        constructor(source: LayoutParams) : super(source)
    }
}

{'fraction_non_alphanumeric': 0.08319848975188782, 'fraction_numerical': 0.005124056094929882, 'mean_word_length': 1.5809987819732034, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4670964', 'n_tokens_mistral': 4386, 'n_tokens_neox': 4231, 'n_words': 824}