content: /**
   * Copyright (c) 2011, Artem Votincev (apmem.org)
   * http://www.apache.org/licenses/LICENSE-2.0.txt
   *
   * Modified by Alexander Brakowski for the purpose of this project
   */
  package dk.aau.netsec.hostage.ui.layouts;
  
  
  import android.content.Context;
  import android.content.res.TypedArray;
  import android.graphics.Canvas;
  import android.graphics.Paint;
  import android.util.AttributeSet;
  import android.view.View;
  import android.view.ViewGroup;
  
  import dk.aau.netsec.hostage.R;
  
  /**
   * Subviews of this View will be positioned in an "flowing" manner.
   *
   * See {@link ://github.com/ApmeM/android-flowlayout}
   */
  public class FlowLayout extends ViewGroup {
  	public static final int HORIZONTAL = 0;
  	public static final int VERTICAL = 1;
  	private int horizontalSpacing = 0;
  	private int verticalSpacing = 0;
  	private int orientation = 0;
  	private boolean debugDraw = false;
  
  	public FlowLayout(Context context) {
  		super(context);
  
  		this.readStyleParameters(context, null);
  	}
  
  	public FlowLayout(Context context, AttributeSet attributeSet) {
  		super(context, attributeSet);
  
  		this.readStyleParameters(context, attributeSet);
  	}
  
  	public FlowLayout(Context context, AttributeSet attributeSet, int defStyle) {
  		super(context, attributeSet, defStyle);
  
  		this.readStyleParameters(context, attributeSet);
  	}
  
  	@Override
  	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  		int sizeWidth = MeasureSpec.getSize(widthMeasureSpec) - this.getPaddingRight() - this.getPaddingLeft();
  		int sizeHeight = MeasureSpec.getSize(heightMeasureSpec) - this.getPaddingTop() - this.getPaddingBottom();
  
  		int modeWidth = MeasureSpec.getMode(widthMeasureSpec);
  		int modeHeight = MeasureSpec.getMode(heightMeasureSpec);
  
  		int size;
  		int mode;
  
  		if (orientation == HORIZONTAL) {
  			size = sizeWidth;
  			mode = modeWidth;
  		} else {
  			size = sizeHeight;
  			mode = modeHeight;
  		}
  
  		int lineThicknessWithSpacing = 0;
  		int lineThickness = 0;
  		int lineLengthWithSpacing = 0;
  		int lineLength;
  
  		int prevLinePosition = 0;
  
  		int controlMaxLength = 0;
  		int controlMaxThickness = 0;
  
  		final int count = getChildCount();
  		for (int i = 0; i < count; i++) {
  			final View child = getChildAt(i);
  			if (child.getVisibility() == GONE) {
  				continue;
  			}
  
  			LayoutParams lp = (LayoutParams) child.getLayoutParams();
  
  			child.measure(
  					getChildMeasureSpec(widthMeasureSpec, this.getPaddingLeft() + this.getPaddingRight(), lp.width),
  					getChildMeasureSpec(heightMeasureSpec, this.getPaddingTop() + this.getPaddingBottom(), lp.height)
  			);
  
  			int hSpacing = this.getHorizontalSpacing(lp);
  			int vSpacing = this.getVerticalSpacing(lp);
  
  			int childWidth = child.getMeasuredWidth();
  			int childHeight = child.getMeasuredHeight();
  
  			int childLength;
  			int childThickness;
  			int spacingLength;
  			int spacingThickness;
  
  			if (orientation == HORIZONTAL) {
  				childLength = childWidth;
  				childThickness = childHeight;
  				spacingLength = hSpacing;
  				spacingThickness = vSpacing;
  			} else {
  				childLength = childHeight;
  				childThickness = childWidth;
  				spacingLength = vSpacing;
  				spacingThickness = hSpacing;
  			}
  
  			lineLength = lineLengthWithSpacing + childLength;
  			lineLengthWithSpacing = lineLength + spacingLength;
  
  			boolean newLine = lp.newLine || (mode != MeasureSpec.UNSPECIFIED && lineLength > size);
  			if (newLine) {
  				prevLinePosition = prevLinePosition + lineThicknessWithSpacing;
  
  				lineThickness = childThickness;
  				lineLength = childLength;
  				lineThicknessWithSpacing = childThickness + spacingThickness;
  				lineLengthWithSpacing = lineLength + spacingLength;
  			}
  
  			lineThicknessWithSpacing = Math.max(lineThicknessWithSpacing, childThickness + spacingThickness);
  			lineThickness = Math.max(lineThickness, childThickness);
  
  			int posX;
  			int posY;
  			if (orientation == HORIZONTAL) {
  				posX = getPaddingLeft() + lineLength - childLength;
  				posY = getPaddingTop() + prevLinePosition;
  			} else {
  				posX = getPaddingLeft() + prevLinePosition;
  				posY = getPaddingTop() + lineLength - childHeight;
  			}
  			lp.setPosition(posX, posY);
  
  			controlMaxLength = Math.max(controlMaxLength, lineLength);
  			controlMaxThickness = prevLinePosition + lineThickness;
  		}
  
          /* need to take paddings into account */
  		if (orientation == HORIZONTAL) {
  			controlMaxLength += getPaddingLeft() + getPaddingRight();
  			controlMaxThickness += getPaddingBottom() + getPaddingTop();
  		} else {
  			controlMaxLength += getPaddingBottom() + getPaddingTop();
  			controlMaxThickness += getPaddingLeft() + getPaddingRight();
  		}
  
  		if (orientation == HORIZONTAL) {
  			this.setMeasuredDimension(resolveSize(controlMaxLength, widthMeasureSpec), resolveSize(controlMaxThickness, heightMeasureSpec));
  		} else {
  			this.setMeasuredDimension(resolveSize(controlMaxThickness, widthMeasureSpec), resolveSize(controlMaxLength, heightMeasureSpec));
  		}
  	}
  
  	private int getVerticalSpacing(LayoutParams lp) {
  		int vSpacing;
  		if (lp.verticalSpacingSpecified()) {
  			vSpacing = lp.verticalSpacing;
  		} else {
  			vSpacing = this.verticalSpacing;
  		}
  		return vSpacing;
  	}
  
  	private int getHorizontalSpacing(LayoutParams lp) {
  		int hSpacing;
  		if (lp.horizontalSpacingSpecified()) {
  			hSpacing = lp.horizontalSpacing;
  		} else {
  			hSpacing = this.horizontalSpacing;
  		}
  		return hSpacing;
  	}
  
  	@Override
  	protected void onLayout(boolean changed, int l, int t, int r, int b) {
  		final int count = getChildCount();
  		for (int i = 0; i < count; i++) {
  			View child = getChildAt(i);
  			LayoutParams lp = (LayoutParams) child.getLayoutParams();
  			child.layout(lp.x, lp.y, lp.x + child.getMeasuredWidth(), lp.y + child.getMeasuredHeight());
  		}
  	}
  
  	@Override
  	protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
  		boolean more = super.drawChild(canvas, child, drawingTime);
  		this.drawDebugInfo(canvas, child);
  		return more;
  	}
  
  	@Override
  	protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
  		return p instanceof LayoutParams;
  	}
  
  	@Override
  	protected LayoutParams generateDefaultLayoutParams() {
  		return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
  	}
  
  	@Override
  	public LayoutParams generateLayoutParams(AttributeSet attributeSet) {
  		return new LayoutParams(getContext(), attributeSet);
  	}
  
  	@Override
  	protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
  		return new LayoutParams(p);
  	}
  
  	private void readStyleParameters(Context context, AttributeSet attributeSet) {
  		TypedArray a = context.obtainStyledAttributes(attributeSet, R.styleable.FlowLayout);
  		try {
  			horizontalSpacing = a.getDimensionPixelSize(R.styleable.FlowLayout_horizontalSpacing, 0);
  			verticalSpacing = a.getDimensionPixelSize(R.styleable.FlowLayout_verticalSpacing, 0);
  			orientation = a.getInteger(R.styleable.FlowLayout_orientation, HORIZONTAL);
  			debugDraw = a.getBoolean(R.styleable.FlowLayout_debugDraw, false);
  		} finally {
  			a.recycle();
  		}
  	}
  
  	private void drawDebugInfo(Canvas canvas, View child) {
  		if (!debugDraw) {
  			return;
  		}
  
  		Paint childPaint = this.createPaint(0xffffff00);
  		Paint layoutPaint = this.createPaint(0xff00ff00);
  		Paint newLinePaint = this.createPaint(0xffff0000);
  
  		LayoutParams lp = (LayoutParams) child.getLayoutParams();
  
  		if (lp.horizontalSpacing > 0) {
  			float x = child.getRight();
  			float y = child.getTop() + child.getHeight() / 2.0f;
  			canvas.drawLine(x, y, x + lp.horizontalSpacing, y, childPaint);
  			canvas.drawLine(x + lp.horizontalSpacing - 4.0f, y - 4.0f, x + lp.horizontalSpacing, y, childPaint);
  			canvas.drawLine(x + lp.horizontalSpacing - 4.0f, y + 4.0f, x + lp.horizontalSpacing, y, childPaint);
  		} else if (this.horizontalSpacing > 0) {
  			float x = child.getRight();
  			float y = child.getTop() + child.getHeight() / 2.0f;
  			canvas.drawLine(x, y, x + this.horizontalSpacing, y, layoutPaint);
  			canvas.drawLine(x + this.horizontalSpacing - 4.0f, y - 4.0f, x + this.horizontalSpacing, y, layoutPaint);
  			canvas.drawLine(x + this.horizontalSpacing - 4.0f, y + 4.0f, x + this.horizontalSpacing, y, layoutPaint);
  		}
  
  		if (lp.verticalSpacing > 0) {
  			float x = child.getLeft() + child.getWidth() / 2.0f;
  			float y = child.getBottom();
  			canvas.drawLine(x, y, x, y + lp.verticalSpacing, childPaint);
  			canvas.drawLine(x - 4.0f, y + lp.verticalSpacing - 4.0f, x, y + lp.verticalSpacing, childPaint);
  			canvas.drawLine(x + 4.0f, y + lp.verticalSpacing - 4.0f, x, y + lp.verticalSpacing, childPaint);
  		} else if (this.verticalSpacing > 0) {
  			float x = child.getLeft() + child.getWidth() / 2.0f;
  			float y = child.getBottom();
  			canvas.drawLine(x, y, x, y + this.verticalSpacing, layoutPaint);
  			canvas.drawLine(x - 4.0f, y + this.verticalSpacing - 4.0f, x, y + this.verticalSpacing, layoutPaint);
  			canvas.drawLine(x + 4.0f, y + this.verticalSpacing - 4.0f, x, y + this.verticalSpacing, layoutPaint);
  		}
  
  		if (lp.newLine) {
  			if (orientation == HORIZONTAL) {
  				float x = child.getLeft();
  				float y = child.getTop() + child.getHeight() / 2.0f;
  				canvas.drawLine(x, y - 6.0f, x, y + 6.0f, newLinePaint);
  			} else {
  				float x = child.getLeft() + child.getWidth() / 2.0f;
  				float y = child.getTop();
  				canvas.drawLine(x - 6.0f, y, x + 6.0f, y, newLinePaint);
  			}
  		}
  	}
  
  	private Paint createPaint(int color) {
  		Paint paint = new Paint();
  		paint.setAntiAlias(true);
  		paint.setColor(color);
  		paint.setStrokeWidth(2.0f);
  		return paint;
  	}
  
  	public static class LayoutParams extends ViewGroup.LayoutParams {
  		private static int NO_SPACING = -1;
  		private int x;
  		private int y;
  		private int horizontalSpacing = NO_SPACING;
  		private int verticalSpacing = NO_SPACING;
  		private boolean newLine = false;
  
  		public LayoutParams(Context context, AttributeSet attributeSet) {
  			super(context, attributeSet);
  			this.readStyleParameters(context, attributeSet);
  		}
  
  		public LayoutParams(int width, int height) {
  			super(width, height);
  		}
  
  		public LayoutParams(ViewGroup.LayoutParams layoutParams) {
  			super(layoutParams);
  		}
  
  		public boolean horizontalSpacingSpecified() {
  			return horizontalSpacing != NO_SPACING;
  		}
  
  		public boolean verticalSpacingSpecified() {
  			return verticalSpacing != NO_SPACING;
  		}
  
  		public void setPosition(int x, int y) {
  			this.x = x;
  			this.y = y;
  		}
  
  		private void readStyleParameters(Context context, AttributeSet attributeSet) {
  			TypedArray a = context.obtainStyledAttributes(attributeSet, R.styleable.FlowLayout_LayoutParams);
  			try {
  				horizontalSpacing = a.getDimensionPixelSize(R.styleable.FlowLayout_LayoutParams_layout_horizontalSpacing, NO_SPACING);
  				verticalSpacing = a.getDimensionPixelSize(R.styleable.FlowLayout_LayoutParams_layout_verticalSpacing, NO_SPACING);
  				newLine = a.getBoolean(R.styleable.FlowLayout_LayoutParams_layout_newLine, false);
  			} finally {
  				a.recycle();
  			}
  		}
  	}
  }
  