content: /*
   * Copyright (C) 2015 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 com.android.setupwizardlib;
  
  import android.content.Context;
  import android.content.res.TypedArray;
  import android.graphics.Canvas;
  import android.graphics.Rect;
  import android.graphics.drawable.Drawable;
  import androidx.annotation.IntDef;
  import androidx.core.view.ViewCompat;
  import androidx.recyclerview.widget.RecyclerView;
  import android.view.View;
  import java.lang.annotation.Retention;
  import java.lang.annotation.RetentionPolicy;
  
  /**
   * An {@link androidx.recyclerview.widget.RecyclerView.ItemDecoration} for RecyclerView to draw
   * dividers between items. This ItemDecoration will draw the drawable specified by {@link
   * #setDivider(android.graphics.drawable.Drawable)} as the divider in between each item by default,
   * and the behavior of whether the divider is shown can be customized by subclassing {@link
   * com.android.setupwizardlib.DividerItemDecoration.DividedViewHolder}.
   *
   * <p>Modified from v14 PreferenceFragment.DividerDecoration.
   */
  public class DividerItemDecoration extends RecyclerView.ItemDecoration {
  
    /* static section */
  
    /**
     * An interface to be implemented by a {@link RecyclerView.ViewHolder} which controls whether
     * dividers should be shown above and below that item.
     */
    public interface DividedViewHolder {
  
      /**
       * Returns whether divider is allowed above this item. A divider will be shown only if both
       * items immediately above and below it allows this divider.
       */
      boolean isDividerAllowedAbove();
  
      /**
       * Returns whether divider is allowed below this item. A divider will be shown only if both
       * items immediately above and below it allows this divider.
       */
      boolean isDividerAllowedBelow();
    }
  
    @Retention(RetentionPolicy.SOURCE)
    @IntDef({DIVIDER_CONDITION_EITHER, DIVIDER_CONDITION_BOTH})
    public @interface DividerCondition {}
  
    public static final int DIVIDER_CONDITION_EITHER = 0;
    public static final int DIVIDER_CONDITION_BOTH = 1;
  
    /** @deprecated Use {@link #DividerItemDecoration(android.content.Context)} */
    @Deprecated
    public static DividerItemDecoration getDefault(Context context) {
      return new DividerItemDecoration(context);
    }
  
    /* non-static section */
  
    private Drawable divider;
    private int dividerHeight;
    private int dividerIntrinsicHeight;
    @DividerCondition private int dividerCondition;
  
    public DividerItemDecoration() {}
  
    public DividerItemDecoration(Context context) {
      final TypedArray a = context.obtainStyledAttributes(R.styleable.SuwDividerItemDecoration);
      final Drawable divider =
          a.getDrawable(R.styleable.SuwDividerItemDecoration_android_listDivider);
      final int dividerHeight =
          a.getDimensionPixelSize(R.styleable.SuwDividerItemDecoration_android_dividerHeight, 0);
      @DividerCondition
      final int dividerCondition =
          a.getInt(
              R.styleable.SuwDividerItemDecoration_suwDividerCondition, DIVIDER_CONDITION_EITHER);
      a.recycle();
  
      setDivider(divider);
      setDividerHeight(dividerHeight);
      setDividerCondition(dividerCondition);
    }
  
    @Override
    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
      if (divider == null) {
        return;
      }
      final int childCount = parent.getChildCount();
      final int width = parent.getWidth();
      final int dividerHeight = this.dividerHeight != 0 ? this.dividerHeight : dividerIntrinsicHeight;
      for (int childViewIndex = 0; childViewIndex < childCount; childViewIndex++) {
        final View view = parent.getChildAt(childViewIndex);
        if (shouldDrawDividerBelow(view, parent)) {
          final int top = (int) ViewCompat.getY(view) + view.getHeight();
          divider.setBounds(0, top, width, top + dividerHeight);
          divider.draw(c);
        }
      }
    }
  
    @Override
    public void getItemOffsets(
        Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
      if (shouldDrawDividerBelow(view, parent)) {
        outRect.bottom = dividerHeight != 0 ? dividerHeight : dividerIntrinsicHeight;
      }
    }
  
    private boolean shouldDrawDividerBelow(View view, RecyclerView parent) {
      final RecyclerView.ViewHolder holder = parent.getChildViewHolder(view);
      final int index = holder.getLayoutPosition();
      final int lastItemIndex = parent.getAdapter().getItemCount() - 1;
      if (isDividerAllowedBelow(holder)) {
        if (dividerCondition == DIVIDER_CONDITION_EITHER) {
          // Draw the divider without consulting the next item if we only
          // need permission for either above or below.
          return true;
        }
      } else if (dividerCondition == DIVIDER_CONDITION_BOTH || index == lastItemIndex) {
        // Don't draw if the current view holder doesn't allow drawing below
        // and the current theme requires permission for both the item below and above.
        // Also, if this is the last item, there is no item below to ask permission
        // for whether to draw a divider above, so don't draw it.
        return false;
      }
      // Require permission from index below to draw the divider.
      if (index < lastItemIndex) {
        final RecyclerView.ViewHolder nextHolder = parent.findViewHolderForLayoutPosition(index + 1);
        if (!isDividerAllowedAbove(nextHolder)) {
          // Don't draw if the next view holder doesn't allow drawing above
          return false;
        }
      }
      return true;
    }
  
    /**
     * Whether a divider is allowed above the view holder. The allowed values will be combined
     * according to {@link #getDividerCondition()}. The default implementation delegates to {@link
     * com.android.setupwizardlib.DividerItemDecoration.DividedViewHolder}, or simply allows the
     * divider if the view holder doesn't implement {@code DividedViewHolder}. Subclasses can override
     * this to give more information to decide whether a divider should be drawn.
     *
     * @return True if divider is allowed above this view holder.
     */
    protected boolean isDividerAllowedAbove(RecyclerView.ViewHolder viewHolder) {
      return !(viewHolder instanceof DividedViewHolder)
          || ((DividedViewHolder) viewHolder).isDividerAllowedAbove();
    }
  
    /**
     * Whether a divider is allowed below the view holder. The allowed values will be combined
     * according to {@link #getDividerCondition()}. The default implementation delegates to {@link
     * com.android.setupwizardlib.DividerItemDecoration.DividedViewHolder}, or simply allows the
     * divider if the view holder doesn't implement {@code DividedViewHolder}. Subclasses can override
     * this to give more information to decide whether a divider should be drawn.
     *
     * @return True if divider is allowed below this view holder.
     */
    protected boolean isDividerAllowedBelow(RecyclerView.ViewHolder viewHolder) {
      return !(viewHolder instanceof DividedViewHolder)
          || ((DividedViewHolder) viewHolder).isDividerAllowedBelow();
    }
  
    /** Sets the drawable to be used as the divider. */
    public void setDivider(Drawable divider) {
      if (divider != null) {
        dividerIntrinsicHeight = divider.getIntrinsicHeight();
      } else {
        dividerIntrinsicHeight = 0;
      }
      this.divider = divider;
    }
  
    /** Gets the drawable currently used as the divider. */
    public Drawable getDivider() {
      return divider;
    }
  
    /** Sets the divider height, in pixels. */
    public void setDividerHeight(int dividerHeight) {
      this.dividerHeight = dividerHeight;
    }
  
    /** Gets the divider height, in pixels. */
    public int getDividerHeight() {
      return dividerHeight;
    }
  
    /**
     * Sets whether the divider needs permission from both the item view holder below and above from
     * where the divider would draw itself or just needs permission from one or the other before
     * drawing itself.
     */
    public void setDividerCondition(@DividerCondition int dividerCondition) {
      this.dividerCondition = dividerCondition;
    }
  
    /**
     * Gets whether the divider needs permission from both the item view holder below and above from
     * where the divider would draw itself or just needs permission from one or the other before
     * drawing itself.
     */
    @DividerCondition
    public int getDividerCondition() {
      return dividerCondition;
    }
  }
  