/*******************************************************************************
 * Copyright (c) 2009, 2016 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.swt.snippets;

/*
 * StyledText: Variable tab stops per line
 *
 * For a list of all SWT example snippets see
 * http://www.eclipse.org/swt/snippets/
 *
 */
import org.eclipse.swt.*;
import org.eclipse.swt.custom.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;

public class Snippet328 {

	public static void main(String[] args) {
		Display display = new Display();
		Shell shell = new Shell(display);
		shell.setText("Snippet 328");
		shell.setLayout(new GridLayout());
		shell.setText("StyledText: Variable tab stops");

		Ruler ruler = new Ruler(shell, SWT.NONE);
		GridData data = new GridData();
		data.heightHint = 10;
		data.horizontalAlignment = SWT.FILL;
		ruler.setLayoutData(data);
		ruler.setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND));

		StyledText styledText = new StyledText (shell, SWT.FULL_SELECTION | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
		styledText.setText("0\t1\t2\t3\t4\nDrag\tthe\ttab\tmarks\ton\ttop\tto\tchange\tthe\tposition\tof\tthe\ttab\tstops");
		styledText.setTabStops(new int[] {30, 70, 90, 140});
		styledText.setLineTabStops(0, 1, new int[] {10, 60, 80});
		styledText.setLineTabStops(1, 1, new int[] {40, 70, 100, 150});
		styledText.setLayoutData(new GridData(GridData.FILL_BOTH));
		ruler.setEditor(styledText);

		shell.setSize(800, 400);
		shell.open();
		while (!shell.isDisposed()) {
			if (!display.readAndDispatch()) display.sleep();
		}
		display.dispose ();
	}

	public static class Ruler extends Canvas {
		StyledText styledText;
		int hover = -1;
		int line = 0;
		public Ruler (Composite parent, int style) {
			super(parent, style | SWT.DOUBLE_BUFFERED);
			Display display = getDisplay();
			setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND));
			Listener listener = e -> {
				switch (e.type) {
					case SWT.Paint:
						handlePaint(e);
						break;
					case SWT.MouseMove:
						if ((e.stateMask & SWT.BUTTON1) != 0) {
							handleDragMark(e);
						} else {
							handleMouseMove(e);
						}
						break;
					case SWT.MouseExit:
						if (hover != -1) redraw();
						hover = -1;
						break;
				}
			};
			addListener(SWT.Paint, listener);
			addListener(SWT.MouseMove, listener);
			addListener(SWT.MouseExit, listener);
		}
		public void setEditor(StyledText editor) {
			styledText = editor;
			styledText.addCaretListener(event -> {
				int caretLine = styledText.getLineAtOffset(event.caretOffset);
				if (caretLine != line) {
					line = caretLine;
					redraw();
				}
			});
		}
		void handleMouseMove(Event e) {
			int [] tabs = styledText.getLineTabStops(line);
			int margin = styledText.getLeftMargin() + styledText.getBorderWidth();
			int count = tabs.length;
			int newIndex = -1;
			int x = margin;
			if (x <= e.x && e.x < x + 5) {
				newIndex = 0;
			}
			int i = 0;
			if (newIndex == -1) {
				for (i = 0; i < count; i++) {
					x = tabs[i] + margin;
					if (x <= e.x && e.x <= x +5) {
						newIndex = i + 1;
						break;
					}
				}
			}
			if (newIndex == -1) {
				int lastTabWidth = count > 1 ? tabs[count-1] - tabs[count-2] : tabs[0];
				x += lastTabWidth;
				Rectangle ca = getClientArea();
				while (x < ca.x + ca.width) {
					if (x <= e.x && e.x <= x +5) {
						newIndex = i + 1;
						break;
					}
					x += lastTabWidth;
					i++;
				}
			}
			if (newIndex != hover) {
				hover = newIndex;
				redraw();
			}
		}

		void handleDragMark (Event e) {
			if (hover <= 0) return;
			int [] tabs = styledText.getLineTabStops(line);
			int margin = styledText.getLeftMargin() + styledText.getBorderWidth();
			int count = tabs.length;
			int x = e.x - margin;
			int index = hover - 1;
			if (index < count) {
				if (index >= count - 2) {
					int last = tabs[count - 1];
					int secondLast = tabs[count - 2];
					int grow = index == count -1 ? 2 : 1;
					int[] newTabs = new int[count + grow];
					System.arraycopy(tabs, 0, newTabs, 0, count);
					newTabs[count] = last + (last - secondLast);
					if (grow == 2) {
						newTabs[count + 1] = last + 2 * (last - secondLast);
					}
					tabs = newTabs;
				}
			} else {
				int[] newTabs = new int[index + 3];
				System.arraycopy(tabs, 0, newTabs, 0, count);
				int last = tabs[count - 1];
				int diff = last - tabs[count - 2];
				for (int i = count; i < newTabs.length; i++) {
					newTabs[i] = last + diff;
					last += diff;
				}
				tabs = newTabs;
			}
			int min = index > 0 ? tabs [index - 1] + 1 : 0;
			if (x < min) x = min;
			int max = tabs[index + 1] - 1;
			if (x > max) {
				int diff = x - tabs[index];
				for (int i = index + 1; i < count; i++) {
					tabs[i] += diff;
				}
			}
			tabs[index] = x;
			styledText.setLineTabStops(line, 1, tabs);
			redraw();
		}
		void handlePaint(Event e) {
			Display display = e.display;
			GC gc = e.gc;
			int [] tabs = styledText.getLineTabStops(line);
			int margin = styledText.getLeftMargin() + styledText.getBorderWidth();
			int x = margin;
			gc.setBackground(display.getSystemColor(hover == 0 ? SWT.COLOR_RED : SWT.COLOR_BLACK));
			gc.fillPolygon(new int[] {x,0, x+5,0, x, 10});
			int i;
			for (i = 0; i < tabs.length; i++) {
				x = tabs[i] + margin;
				if (x > e.x + e.width) break;
				gc.setBackground(display.getSystemColor(hover == i + 1 ? SWT.COLOR_RED : SWT.COLOR_BLACK));
				gc.fillPolygon(new int[] {x,0, x+5,0, x, 10});
			}
			int lastTabWidth = tabs.length > 1 ? tabs[tabs.length-1] - tabs[tabs.length-2] : tabs[0];
			x += lastTabWidth;
			while (x < e.x + e.width) {
				gc.setBackground(display.getSystemColor(hover == ++i ? SWT.COLOR_RED : SWT.COLOR_BLACK));
				gc.fillPolygon(new int[] {x,0, x+5,0, x, 10});
				x += lastTabWidth;
			}
		}
	}
}
