// Copyright 2005, Danger, Inc.  All Rights Reserved.
// This file is subject to the Danger, Inc. Sample Code License,
// which is provided in the file SAMPLE_CODE_LICENSE.
// Copies are also available from http://developer.danger.com/

package com.danger.text;

import danger.ui.*;
import danger.util.*;
import danger.text.span.*;

/**
 * This window has an EditText with a post-change notifier that
 * makes sure it matches the North American Dialing Plan
 * phone number format.  For simple cases where you just want
 * to limit what can be typed, you really want to use a
 * TextInputFilter instead; reserve this for cases where
 * you need to add or remove other context around what the
 * user is typing.
 */
public class
Formatting
extends DemoWindow
{
	public
	Formatting()
	{
		StaticTextBox st = new StaticTextBox();
		st.setHasBorder(false);
		st.setAutoResize(true);
		st.setWidth(getWidth());
		st.setText(getApplication().getResources().getString(Resources.ID_FORMAT_TITLE));
		st.show();
		addChild(st);

		EditText et = new FormatTextBox();

		et.setTop(st.getHeight());
		et.setSize(getWidth(), getHeight() - st.getHeight());
		et.show();
		addChild(et);
		setFocusedChild(et);

		setTitle(getApplication().getString(Resources.ID_DEMO_FORMATTING));
	}

	private static class
	FormatTextBox
	extends EditText
	{
		/**
		 * You can alter the contents of the buffer from this method
		 * or from a TextWatcherSpan's afterTextChanged().  You have
		 * to be careful about reentrancy because this method will
		 * get called recursively from each text change you make.
		 * In this example, I have it make only one change at a time
		 * to avoid getting confused about what changes might have
		 * also been made by the inner notifications.
		 */
		protected void
		afterTextChanged()
		{
			int dig = countDigits();
			String format;

			if (dig <= 7)
				format = "NNN-NNNN";
			else
				format = "(NNN) NNN-NNNN";

			while (enforceFormat(format))
				;

			super.afterTextChanged();
		}

		private int
		countDigits()
		{
			int dig = 0;
			int len = length();

			for (int i = 0; i < len; i++)
				if (Character.isDigit(charAt(i)))
					dig++;

			return dig;
		}

		private boolean
		enforceFormat(String format)
		{
			TextBufferLike tb = (TextBufferLike) getContents();
			int flen = format.length();

			for (int i = 0; i < flen; i++)
			{
				if (i >= length())
					return false;

				char c = format.charAt(i);

				if (c == 'N')
				{
					if (!Character.isDigit(charAt(i)))
					{
						tb.setInsertionPoint(i + 1);
						tb.delete(1);
						return true;
					}
				}
				else
				{
					char tc;

					if ((tc = charAt(i)) != c)
					{
						if (Character.isDigit(tc))
						{
							tb.setInsertionPoint(i);
							tb.insertChar(c);
							return true;
						}
						else
						{
							tb.setInsertionPoint(i + 1);
							tb.delete(1);
							return true;
						}
					}
				}
			}

			if (length() > flen)
			{
				tb.setInsertionPoint(length());
				tb.delete(length() - flen);
				return true;
			}

			return false;
		}
	}
}
