/*
* Copyright 2008-2013, ETH Zürich, Samuel Welten, Michael Kuhn, Tobias Langner,
* Sandro Affentranger, Lukas Bossard, Michael Grob, Rahul Jain,
* Dominic Langenegger, Sonia Mayor Alonso, Roger Odermatt, Tobias Schlueter,
* Yannick Stucki, Sebastian Wendland, Samuel Zehnder, Samuel Zihlmann,
* Samuel Zweifel
*
* This file is part of Jukefox.
*
* Jukefox is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or any later version. Jukefox is
* distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* Jukefox. If not, see <http://www.gnu.org/licenses/>.
*/
package ch.ethz.dcg.pancho3.tablet.widget;
import android.content.Context;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.ViewGroup.LayoutParams;
import android.widget.TextView;
public class SmallestAreaTextView extends TextView {
// Attributes
private String text;
private Paint mTestPaint;
private TextView testTextView;
public SmallestAreaTextView(Context context) {
super(context);
initialise();
setSingleLine(false);
}
public SmallestAreaTextView(Context context, AttributeSet attrs) {
super(context, attrs);
initialise();
}
private void initialise() {
mTestPaint = new Paint();
mTestPaint.set(this.getPaint());
testTextView = new TextView(getContext());
testTextView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
testTextView.setSingleLine(false);
}
/*
* Rearrange the text, so that the area of the text box is minimal.
*/
private void refitText(String text) {
if ((text == null) || (mTestPaint == null)) {
return;
}
testTextView.setTextSize(getTextSize());
String[] parts = text.split(" ");
mTestPaint.set(this.getPaint());
mTestPaint.setTextSize(getTextSize());
// Find the best line-breaking to get the smallest area
float minArea = Float.MAX_VALUE;
for (int i = 0; i < (1 << (parts.length - 1)); ++i) { // 2^{parts.length - 1}
StringBuffer sb = new StringBuffer(text.length());
sb.append(parts[0]);
for (int j = 1; j < parts.length; ++j) {
if ((i & (1 << (j - 1))) > 0) { // is this bit set?
sb.append('\n');
} else {
sb.append(' ');
}
sb.append(parts[j]);
}
String testText = sb.toString();
// Calculate the area of the text
testTextView.setText(testText);
testTextView.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
int ww = testTextView.getMeasuredWidth();
int hh = testTextView.getMeasuredHeight();
/*String[] lines = testText.split("\n");
final int LINE_PADDING = 2;
int w = 0;
int h = -LINE_PADDING; // First line needs no padding
for (String line : lines) {
Rect rect = new Rect();
mTestPaint.getTextBounds(line, 0, line.length(), rect);
w = Math.max(w, rect.width());
h += LINE_PADDING + rect.height();
}
float textSize = getTextSize();
assert textSize > 0;*/
if (minArea > ww * hh) {
minArea = ww * hh;
this.text = testText;
}
}
setText(this.text);
}
@Override
protected void onTextChanged(final CharSequence text, final int start,
final int before, final int after) {
String txt = text.toString();
if (!txt.equals(this.text)) {
refitText(txt);
}
}
}