/*
 * Copyright 2016 Philip Cohn-Cort
 *
 * 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 com.fuzz.indicator;

import android.graphics.Matrix;
import android.support.annotation.NonNull;
import android.text.Spannable;
import android.widget.ImageView;
import android.widget.LinearLayout;

import com.fuzz.indicator.style.MigratoryRange;
import com.fuzz.indicator.style.MigratorySpan;

/**
 * Collection of utility methods for offsetting specific views.
 * <p>
 *     Right now there's just one for {@link ImageView}s, but more
 *     might appear in future.
 * </p>
 *
 * @author Philip Cohn-Cort (Fuzz)
 */
public class OffSetters {
    /**
     * Sets a new image matrix on this view. This method only allows orthogonal offsets
     *
     * @param imageView the view that will be changed
     * @param orientation direction to offset in. Use either {@link LinearLayout#VERTICAL} or {@link LinearLayout#HORIZONTAL}
     * @param percentage  percentage of width/height to offset by - positive means down/right, negative means up/left
     * @param mat         a starting form for the matrix. Callers may choose to supply a new instance of {@link Matrix}
     * @see ImageView#setImageMatrix(Matrix)
     */
    public static void offsetImageBy(@NonNull ImageView imageView, int orientation, float percentage, @NonNull Matrix mat) {
        float offsetX, offsetY;
        if (orientation == LinearLayout.VERTICAL) {
            offsetX = 0;
            offsetY = percentage * imageView.getHeight();
        } else {
            offsetX = percentage * imageView.getWidth();
            offsetY = 0;
        }
        mat.setTranslate(offsetX, offsetY);
        imageView.setImageMatrix(mat);
    }

    public static void offsetSpansBy(@NonNull Spannable spannable, int orientation, float percentage) {
        int length = spannable.length();
        int offset = (int) (percentage * length);

        MigratorySpan[] knownSpans = spannable.getSpans(0, length, MigratorySpan.class);
        if (knownSpans.length > 0) {
            MigratoryRange<Integer> fullSize = MigratoryRange.from(0, length);
            for (MigratorySpan knownSpan : knownSpans) {
                offsetSpan(spannable, fullSize, knownSpan, offset);
            }
        }
    }

    public static void offsetSpan(@NonNull Spannable spannable, MigratoryRange<Integer> fullSize, MigratorySpan knownSpan, int offset) {
        MigratoryRange<Integer> covered = knownSpan.getCoverage(spannable).translate(offset);
        int spanStart = fullSize.clamp(covered.getLower());
        int spanEnd = fullSize.clamp(covered.getUpper());
        int flags = knownSpan.preferredFlags(spannable.getSpanFlags(knownSpan));
        spannable.setSpan(knownSpan, spanStart, spanEnd, flags);
    }
}

@@ -797,16 +797,48 @@
 rLayout;
+%0Aimport android.widget.TextView;
 %0A%0Aimport
@@ -1058,16 +1058,53 @@
 geView%7Ds
+ and one for%0A *     %7B@link TextView%7Ds
 , but mo
@@ -2270,32 +2270,755 @@
 ix(mat);%0A    %7D%0A%0A
+    /**%0A     * Ensures that all spans of type %7B@link MigratorySpan%7D within %7B@code spannable%7D are%0A     * translated a proportional quantity of characters from their baseline position. Each%0A     * span's implementation of %7B@link MigratorySpan#getCoverage(Spannable)%7D is responsible%0A     * for reporting the correct baseline coverage prior to translation.%0A     *%0A     * @param spannable      the text to which the spans are attached%0A     * @param orientation    direction of offset (currently not used)%0A     * @param fraction       what proportion of the spannable should be considered offset.%0A     *                       values outside the range of 0..1 will be clamped into that%0A     *                       range.%0A     */%0A
     public stati
@@ -3091,26 +3091,24 @@
 , float 
-percentage
+fraction
 ) %7B%0A    
@@ -3172,26 +3172,24 @@
  (int) (
-percentage
+fraction
  * lengt

Update javadoc in OffSetters.java