// 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 java.util.Random;
import danger.ui.*;
import danger.util.*;
import danger.text.span.*;

/**
 * This class has a text box with a bunch of nested margins to
 * demonstrate how they are drawn from largest scope to
 * smallest scope.  It also demonstrates how right margin drawing
 * is a little different from left margin drawing.
 */
public class
NestedMargins
extends DemoWindow
{
	public
	NestedMargins()
	{
		ScrollingTextBox stb = new ScrollingTextBox();

		stb.setSize(getWidth(), getHeight());
		stb.setBorderShowsScrolling(true);
		stb.show();
		addChild(stb);
		setFocusedChild(stb);

		String[] pars = getApplication().getResources().getStringArray(Resources.ID_CONVERSATION);
		int[] starts = new int[pars.length + 1];

		TextBuffer tb = new TextBuffer();

		for (int i = 0; i < pars.length; i++)
		{
			starts[i] = tb.length();

			tb.insert(pars[i]);
			tb.insert("\r\r");
		}

		starts[pars.length] = tb.length();

		Random r = new Random();

		for (int i = 0; i < 20; i++)
		{
			int color = r.nextInt(7);
			color = 255 * (color & 1) + (255 << 7) * (color & 2) + (255 << 14) * (color & 4);

			ParagraphSpan ps;

			if (r.nextBoolean())
				ps = new LeftStripe(color);
			else
				ps = new RightStripe(color);

			int start = 0, end = 0; // appease compiler

			// Keep this one we're adding from overlapping any other
			// margins of the same type whose text is not either
			// a subset or a superset of this one, since there's
			// not really any sensible way to display that.

			boolean again = true;
			while (again)
			{
				start = starts[r.nextInt(starts.length)];
				end = starts[r.nextInt(starts.length)];

				if (end < start)
				{
					int tmp = end;
					end = start;
					start = tmp;
				}

				again = false;
				Object[] spans = tb.getSpansOverlapping(start, end, ps.getClass());
				if (spans != null)
				{
					for (int j = 0; j < spans.length; j++)
					{
						int s = tb.getSpanStart(spans[j]);
						int e = tb.getSpanEnd(spans[j]);

						if (end <= s)
							continue;
						if (start >= e)
							continue;
						if (start <= s && end >= e)
							continue;
						if (start >= s && end <= e)
							continue;

						again = true;
					}
				}
			}

			tb.setSpan(ps, start, end, Spannable.SPAN_INCLUSIVE_EXCLUSIVE | Spannable.SPAN_PARAGRAPH);
		}

		stb.setText(tb);

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

	private static class
	LeftStripe
	implements LeftMarginSpan
	{
		public
		LeftStripe(int color)
		{
			mColor = color;
		}

		public int
		modifyLeftMargin(int margin, Object[] spans, Font f, CharSequence text, int parStart, int lineStart, int paragraphDistance)
		{
			return margin + WIDTH;
		}

		public int
		drawLeftMargin(Pen p, int x, int top, int baseline, int bottom, Object[] spans, CharSequence text, int parStart, int lineStart, int paragraphDistance, Object[] characterSpans)
		{
			CharacterSpan.Set.drawBlank(p, x, WIDTH, top, baseline, bottom, characterSpans);

			p.push();
			p.setColor(mColor);
			p.fillRect(x, top, x + 2, bottom);
			p.pop();

			return WIDTH;
		}

		private int mColor;
		private static final int WIDTH = 4;
	}

	private static class
	RightStripe
	implements RightMarginSpan
	{
		public
		RightStripe(int color)
		{
			mColor = color;
		}

		public int
		modifyRightMargin(int margin, Object[] spans, Font f, CharSequence text, int parStart, int lineStart, int paragraphDistance)
		{
			return margin + WIDTH;
		}

		/**
		 * The thing to note here is that the x parameter is the *right*
		 * edge of this margin, not the left, so you have to subtract the
		 * margin width from it in all the calls that do the drawing.
		 */
		public int
		drawRightMargin(Pen p, int x, int top, int baseline, int bottom, Object[] spans, CharSequence text, int parStart, int lineStart, int paragraphDistance, Object[] characterSpans)
		{
			CharacterSpan.Set.drawBlank(p, x - WIDTH, WIDTH, top, baseline, bottom, characterSpans);

			p.push();
			p.setColor(mColor);
			p.fillRect(x - 2, top, x, bottom);
			p.pop();

			return WIDTH;
		}

		private int mColor;
		private static final int WIDTH = 4;
	}
}
