Blob Blame Raw
package com.icystar.dicegenerator;

import java.util.Stack;

import android.content.Context;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.ImageView.ScaleType;
import android.widget.TextView;

import com.icystar.dicegenerator.MainActivity.Drop;

public class ResizerFrameLayout extends FrameLayout {

	public static class Measures {
		public Typeface typeface;
		public float indicatorFontSize;
		public float numberFontSize;
		public float buttonFontSize;
		public int indicatorButtonSize;
		public int historyItemWidth;
		public int dicesItemWidth;
		public int padding;
		
		public float fitText(String text, TextPaint textPaint, int w, int h) {
			float max = 100.f;
			float min = 2.f;
			float precision = 0.5f;
			
			while (max - min > precision) {
				float current = (max + min)/2.f;
				textPaint.setTextSize(current);
				Rect bounds = new Rect();
				textPaint.getTextBounds(text, 0, text.length(), bounds);
				int tw = Math.max(bounds.right, 0) - Math.min(bounds.left, 0); 
				int th = Math.max(bounds.bottom, 0) - Math.min(bounds.top, 0); 
				if (tw >= w || th >= h)
					max = current;
				else
					min = current;
			}
			
			return min;
		}
		
		public float widthOfText(String text, TextPaint textPaint, float size) {
			textPaint.setTextSize(size);
			Rect bounds = new Rect();
			textPaint.getTextBounds(text, 0, text.length(), bounds);
			return Math.max(bounds.right, 0) - Math.min(bounds.left, 0); 
		}
		
		public Measures(int width, int height, TextPaint textPaint) {
			typeface = textPaint.getTypeface();
			
			padding = width/40;
			indicatorButtonSize = Math.min(width/6, height/5);
			
			int indicatorWidth = width - indicatorButtonSize*2;
			if (width > height && indicatorWidth > width/2) indicatorWidth = width/2;
			int indicatorTextWidth = indicatorWidth - padding*2;
			indicatorFontSize = fitText(Drop.template, textPaint, indicatorTextWidth, indicatorButtonSize/3);

			int buttonWidth = Math.round((float)width/3.f/1.5f);
			int buttonHeight = Math.round((float)(height-indicatorButtonSize)/4.f/3.f);
			numberFontSize = fitText("0", textPaint, buttonWidth, buttonHeight);
			buttonFontSize = fitText("Mmmm", textPaint, buttonWidth, buttonHeight);

			historyItemWidth = Math.round(widthOfText(Drop.template, textPaint, indicatorFontSize)) + 1 + padding*2;
			historyItemWidth = historyItemWidth > width ? width : width / (width/historyItemWidth) - 1;
			dicesItemWidth = Math.round(widthOfText(Drop.diceTemplate, textPaint, indicatorFontSize)) + 1 + padding*3;
		}
	}
	
	public int appliedWidth = 0;
	public int appliedHeight = 0;
	public boolean needLayout = false;
	public TextPaint textPaint; 
	public Stack<Runnable> afterLayout = new Stack<Runnable>();
	public Runnable requestLayoutPost;
	
	public ResizerFrameLayout(Context context) {
		super(context);
		initialize();
	}

	public ResizerFrameLayout(Context context, AttributeSet attrs) {
		super(context, attrs);
		initialize();
	}

	public ResizerFrameLayout(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		initialize();
	}
	
	void initialize() {
		requestLayoutPost = new Runnable() {
			@Override
			public void run() {
				requestLayout();
			}
		};
		TextView textView = new TextView(getContext());
		textPaint = new TextPaint(textView.getPaint());
	}

	@Override
	protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
		super.onLayout(changed, left, top, right, bottom);
		
		int w = right - left;
		int h = bottom - top;
		if (!isInEditMode() && (appliedWidth != w || appliedHeight != h)) {
			appliedWidth = w;
			appliedHeight = h;
			setMeasures(this, new Measures(appliedWidth, appliedHeight, textPaint));
			
			if (!isInEditMode()) post(requestLayoutPost);
		} else {
			if (!isInEditMode())
				while (afterLayout.size() > 0)
					post(afterLayout.pop());
		}
	}
	
	void setMeasures(View view, Measures measures) {
		String tag = view.getTag() == null ? "" : view.getTag().toString();

		if (view instanceof ImageButton) {
			ImageButton imageButton = (ImageButton)view;
			imageButton.setMaxHeight(measures.indicatorButtonSize);
			imageButton.setMaxWidth(measures.indicatorButtonSize);
			imageButton.setMinimumWidth(measures.indicatorButtonSize);
			imageButton.setMinimumHeight(measures.indicatorButtonSize);
			imageButton.setScaleType(ScaleType.CENTER_INSIDE);
			ViewGroup.LayoutParams layoutParams = imageButton.getLayoutParams();
			layoutParams.width = measures.indicatorButtonSize;
			layoutParams.height = measures.indicatorButtonSize;
			imageButton.setLayoutParams(layoutParams);
		} else
		if (view instanceof Button) {
			Button button = (Button)view;
			button.setTypeface(measures.typeface);
			if (tag.compareTo("historyActivityButton") == 0) {
				button.setTextSize(TypedValue.COMPLEX_UNIT_PX, measures.indicatorFontSize);
			} else
			if (button.getText().length() == 1)
				button.setTextSize(TypedValue.COMPLEX_UNIT_PX, measures.numberFontSize);
			else
				button.setTextSize(TypedValue.COMPLEX_UNIT_PX, measures.buttonFontSize);
		} else
		if (view instanceof TextView) {
			TextView textView = (TextView)view;
			if (tag.compareTo("indicator") == 0) {
				textView.setMaxHeight(measures.indicatorButtonSize);
				textView.setMinHeight(measures.indicatorButtonSize);
				textView.setHeight(measures.indicatorButtonSize);
				textView.setLineSpacing(0.f, 100.f);
			} else
			if (tag.compareTo("historyItem") == 0) {
				textView.setMaxWidth(measures.historyItemWidth);
				textView.setMinWidth(measures.historyItemWidth);
				textView.setWidth(measures.historyItemWidth);
			} else
			if (tag.compareTo("dicesItem") == 0) {
				textView.setMaxWidth(measures.dicesItemWidth);
				textView.setMinWidth(measures.dicesItemWidth);
				textView.setWidth(measures.dicesItemWidth);
			}

			textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, measures.indicatorFontSize);
			textView.setPadding(measures.padding, 0, measures.padding, 0);
			textView.setTypeface(measures.typeface);
			textView.requestLayout();
		} else
		if (view instanceof ViewGroup) {
			ViewGroup viewGroup = (ViewGroup)view; 
			for(int i = 0; i < viewGroup.getChildCount(); i++)
				setMeasures(viewGroup.getChildAt(i), measures);
		}
	}
}