/*
	Thinlet GUI toolkit - www.thinlet.com
	Copyright (C) 2002 Robert Bajzat (robert.bajzat@thinlet.com)

	This library is free software; you can redistribute it and/or
	modify it under the terms of the GNU Lesser General Public
	License as published by the Free Software Foundation; either
	version 2.1 of the License, or (at your option) any later version.

	This library 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
	Lesser General Public License for more details.

	You should have received a copy of the GNU Lesser General Public
	License along with this library; if not, write to the Free Software
	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

//package thinlet; //java
//midp package thinlet.midp;

import java.awt.*; //java
import java.awt.<error descr="Cannot resolve symbol 'datatransfer'">datatransfer</error>.*; //java
import java.awt.<error descr="Cannot resolve symbol 'image'">image</error>.*; //java
import java.awt.event.*; //java
import java.lang.reflect.*; //java
import java.io.*;
import java.net.*; //java
import java.util.*;
//midp import javax.microedition.lcdui.*;
//midp import javax.microedition.midlet.*;

/**
 *
 */
class Thinlet extends Container //java
	implements Runnable, Serializable { //java
//midp public class Thinlet extends Canvas implements CommandListener {

	//midp private static final Boolean TRUE = new Boolean(true);
	//midp private static final Boolean FALSE = new Boolean(false);

	//midp private transient Font font;
	private transient <error descr="Cannot resolve symbol 'Color'">Color</error> c_bg;
	private transient <error descr="Cannot resolve symbol 'Color'">Color</error> c_text;
	private transient <error descr="Cannot resolve symbol 'Color'">Color</error> c_textbg;
	private transient <error descr="Cannot resolve symbol 'Color'">Color</error> c_border;
	private transient <error descr="Cannot resolve symbol 'Color'">Color</error> c_disable;
	private transient <error descr="Cannot resolve symbol 'Color'">Color</error> c_hover;
	private transient <error descr="Cannot resolve symbol 'Color'">Color</error> c_press;
	private transient <error descr="Cannot resolve symbol 'Color'">Color</error> c_focus;
	private transient <error descr="Cannot resolve symbol 'Color'">Color</error> c_select;
	private transient <error descr="Cannot resolve symbol 'Color'">Color</error> c_ctrl = null; //java
	//midp private transient Color c_ctrl;
	private transient int block;
	private transient <error descr="Cannot resolve symbol 'Image'">Image</error> gradient; //java
	{
		setFont(new <error descr="Cannot resolve symbol 'Font'">Font</error>("SansSerif", <error descr="Cannot resolve symbol 'Font'">Font</error>.PLAIN, 12)); //java
		//midp setFont(Font.getDefaultFont());
		setColors(0xe6e6e6, 0x000000, 0xffffff,
			0x909090, 0xb0b0b0, 0xededed, 0xb9b9b9, 0x89899a, 0xc5c5dd); // f99237 eac16a // e68b2c ffc73c
	}

	private transient Thread timer;
	private transient long watchdelay;
	private transient long watch;
	private transient String clipboard;

	private Object content = createImpl("desktop");
	private transient Object mouseinside;
	private transient Object insidepart;
	private transient Object mousepressed;
	private transient Object pressedpart;
	private transient int referencex, referencey;
	private transient int mousex, mousey;
	private transient Object focusowner;
	private transient boolean focusinside; //midp { focusinside = true; }
	private transient Object popupowner;
	private transient Object tooltipowner;
	//private transient int pressedkey;

	//java>
	private static final int DRAG_ENTERED = <error descr="Cannot resolve symbol 'AWTEvent'">AWTEvent</error>.RESERVED_ID_MAX + 1;
	private static final int DRAG_EXITED = <error descr="Cannot resolve symbol 'AWTEvent'">AWTEvent</error>.RESERVED_ID_MAX + 2;

	private static long WHEEL_MASK = 0;
	private static int MOUSE_WHEEL = 0;
	private static <error descr="Cannot resolve symbol 'Method'">Method</error> wheelrotation = null;
	static {
		try {
			WHEEL_MASK = <error descr="Cannot resolve symbol 'AWTEvent'">AWTEvent</error>.class.getField("MOUSE_WHEEL_EVENT_MASK").getLong(null);
			MOUSE_WHEEL = <error descr="Cannot resolve symbol 'MouseEvent'">MouseEvent</error>.class.getField("MOUSE_WHEEL").getInt(null);
		} catch (Exception exc) { /* not 1.4 */ }
	}
	{
		if (MOUSE_WHEEL != 0) { // disable global focus-manager for this component in 1.4
			try {
				getClass().getMethod("setFocusTraversalKeysEnabled", new Class[] { Boolean.TYPE }).
					<error descr="Cannot resolve method 'invoke(Thinlet, Object[])'">invoke</error>(this, new Object[] { Boolean.FALSE });
			} catch (Exception exc) { /* never */ }
		}
		enableEvents(<error descr="Cannot resolve symbol 'AWTEvent'">AWTEvent</error>.COMPONENT_EVENT_MASK |
			<error descr="Cannot resolve symbol 'AWTEvent'">AWTEvent</error>.FOCUS_EVENT_MASK | <error descr="Cannot resolve symbol 'AWTEvent'">AWTEvent</error>.KEY_EVENT_MASK |
			<error descr="Cannot resolve symbol 'AWTEvent'">AWTEvent</error>.MOUSE_EVENT_MASK | <error descr="Cannot resolve symbol 'AWTEvent'">AWTEvent</error>.MOUSE_MOTION_EVENT_MASK | WHEEL_MASK);
	}
	//<java

	/**
	 *
	 */
	public void setColors(int background, int text, int textbackground,
			int border, int disable, int hover, int press,
			int focus, int select) {
		c_bg = new <error descr="Cannot resolve symbol 'Color'">Color</error>(background); c_text = new <error descr="Cannot resolve symbol 'Color'">Color</error>(text);
		c_textbg = new <error descr="Cannot resolve symbol 'Color'">Color</error>(textbackground); c_border = new <error descr="Cannot resolve symbol 'Color'">Color</error>(border);
		c_disable = new <error descr="Cannot resolve symbol 'Color'">Color</error>(disable); c_hover = new <error descr="Cannot resolve symbol 'Color'">Color</error>(hover);
		c_press = new <error descr="Cannot resolve symbol 'Color'">Color</error>(press); c_focus = new <error descr="Cannot resolve symbol 'Color'">Color</error>(focus);
		c_select = new <error descr="Cannot resolve symbol 'Color'">Color</error>(select);
		//midp c_ctrl = c_hover;
		//java>
		int[] pix = new int[block * block];
		int r1 = c_bg.<error descr="Cannot resolve method 'getRed()'">getRed</error>(); int r2 = c_press.<error descr="Cannot resolve method 'getRed()'">getRed</error>();
		int g1 = c_bg.<error descr="Cannot resolve method 'getGreen()'">getGreen</error>(); int g2 = c_press.<error descr="Cannot resolve method 'getGreen()'">getGreen</error>();
		int b1 = c_bg.<error descr="Cannot resolve method 'getBlue()'">getBlue</error>(); int b2 = c_press.<error descr="Cannot resolve method 'getBlue()'">getBlue</error>();
		for (int i = 0; i < block; i++) {
			int r = r1 - (r1 - r2) * i / block;
			int g = g1 - (g1 - g2) * i / block;
			int b = b1 - (b1 - b2) * i / block;
			int color = (255 << 24) | (r << 16) | (g << 8) | b;
			for (int j = 0; j < block; j++) {
				pix[i * block + j] = color;
				//pix[j * block + i] = color;
			}
		}
		gradient = createImage(new <error descr="Cannot resolve symbol 'MemoryImageSource'">MemoryImageSource</error>(block, block, pix, 0, block));
		//<java
	}

	/**
	 *
	 */
	public void setFont(<error descr="Cannot resolve symbol 'Font'">Font</error> font) {
		block = getFontMetrics(font).<error descr="Cannot resolve method 'getHeight()'">getHeight</error>(); //java
		super.setFont(font); //java
		//midp block = font.getHeight();
		//midp this.font = font;
	}

	/**
	 *
	 */
	private void doLayout(Object component) {
		String classname = getClass(component);
		if ("combobox" == classname) {
			if (getBoolean(component, "editable", true)) {
				<error descr="Cannot resolve symbol 'Image'">Image</error> icon = getIcon(component, "icon", null);
				layoutField(component, block, false,
					(icon != null) ? icon.<error descr="Cannot resolve method 'getWidth(Thinlet)'">getWidth</error>(this) : 0);
			} // set editable -> validate (overwrite textfield repaint)
			else {
				int selected = getInteger(component, "selected", -1);
				if (selected != -1) {
					Object choice = getItem(component, "choice", selected);
					set(component, "text", get(choice, "text"));
					set(component, "icon", get(choice, "icon"));
				}
			}
		}
		else if (("textfield" == classname) || ("passwordfield" == classname)) {
			layoutField(component, 0, ("passwordfield" == classname), 0);
		}
		else if ("textarea" == classname) {
			String text = getString(component, "text", "");
			int start = getInteger(component, "start", 0);
			if (start > text.length()) { setInteger(component, "start", start = text.length(), 0); }
			int end = getInteger(component, "end", 0);
			if (end > text.length()) { setInteger(component, "end", end = text.length(), 0); }
			int caretx = 0; int carety = 0;
			<error descr="Cannot resolve symbol 'FontMetrics'">FontMetrics</error> fm = getFontMetrics(getFont()); //java
			int width = 0, height = 0;
			for (int i = 0, j = 0; j != -1; i = j + 1) {
				j = text.indexOf('\n', i);
				if (i != j) { // && i != text.length()
					String line = (j != -1) ? text.substring(i, j) : text.substring(i); //java
					width = Math.max(width, fm.<error descr="Cannot resolve method 'stringWidth(String)'">stringWidth</error>(line)); //java
					//midp width = font.substringWidth(text, i, ((j != -1) ? j : text.length()) - i);
				}
				if ((end >= i) && ((j == -1) || (end <= j))) {
					caretx = fm.<error descr="Cannot resolve method 'stringWidth(String)'">stringWidth</error>(text.substring(i, end)); //java
					//midp caretx = font.substringWidth(text, i, end - i);
					carety = height;
				}
				height += fm.<error descr="Cannot resolve method 'getHeight()'">getHeight</error>();
			}
			layoutScrollPane(component, width + 2,
				height - fm.<error descr="Cannot resolve method 'getLeading()'">getLeading</error>() + 2, 0, 0);
			scrollToVisible(component, caretx, carety,
				2, fm.<error descr="Cannot resolve method 'getAscent()'">getAscent</error>() + fm.<error descr="Cannot resolve method 'getDescent()'">getDescent</error>() + 2);
		}
		else if ("tabbedpane" == classname) {
			<error descr="Cannot resolve symbol 'Rectangle'">Rectangle</error> bounds = getRectangle(component, "bounds");
			String placement = getString(component, "placement", "top");
			boolean horizontal = ((placement == "top") || (placement == "bottom"));
			int tabd = 0;
			int tabsize = 0;
			for (Object comp = get(component, "tab");
					comp != null; comp = get(comp, ":next")) {
				Dimension d = getSize(comp, 8, 4, "left");
				setRectangle(comp, "bounds",
					horizontal ? tabd : 0, horizontal ? 0 : tabd, d.width, d.height);
				tabd += horizontal ? d.width : d.height;
				tabsize = Math.max(tabsize, horizontal ? d.height : d.width);
			}
			for (Object comp = get(component, "tab");
					comp != null; comp = get(comp, ":next")) {
				<error descr="Cannot resolve symbol 'Rectangle'">Rectangle</error> r = getRectangle(comp, "bounds");
				if (horizontal) {
					if (placement == "bottom") { r.<error descr="Cannot resolve symbol 'y'">y</error> = bounds.<error descr="Cannot resolve symbol 'height'">height</error> - tabsize; }
					r.<error descr="Cannot resolve symbol 'height'">height</error> = tabsize;
				} else {
					if (placement == "right") { r.<error descr="Cannot resolve symbol 'x'">x</error> = bounds.<error descr="Cannot resolve symbol 'width'">width</error> - tabsize; }
					r.<error descr="Cannot resolve symbol 'width'">width</error> = tabsize;
				}
			}
			int cx = (placement == "left") ? (tabsize + 1) : 2;
			int cy = (placement == "top") ? (tabsize + 1) : 2;
			int cwidth = bounds.<error descr="Cannot resolve symbol 'width'">width</error> - (horizontal ? 4 : (tabsize + 3));
			int cheight = bounds.<error descr="Cannot resolve symbol 'height'">height</error> - (horizontal ? (tabsize + 3) : 4);
			for (Object comp = get(component, "component");
					comp != null; comp = get(comp, ":next")) {
				if (!getBoolean(comp, "visible", true)) { continue; }
				setRectangle(comp, "bounds", cx, cy, cwidth, cheight);
				doLayout(comp);
			}
		}
		else if (("panel" == classname) || (classname == "dialog")) {
			int gap = getInteger(component, "gap", 0);
			int[][] grid = getGrid(component, gap);
			if (grid != null) {
				int top = getInteger(component, "top", 0);
				int left = getInteger(component, "left", 0);
				int bottom = getInteger(component, "bottom", 0);
				int right = getInteger(component, "right", 0);
				if (classname == "dialog") {
					int titleheight = getInteger(component, "titleheight", 0);
					top += 4 + titleheight; left += 4; bottom += 4; right += 4;
				}

				<error descr="Cannot resolve symbol 'Rectangle'">Rectangle</error> bounds = getRectangle(component, "bounds");
				for (int i = 0; i < 2; i++) {
					int d = ((i == 0) ? (bounds.<error descr="Cannot resolve symbol 'width'">width</error> - left - right) :
						(bounds.<error descr="Cannot resolve symbol 'height'">height</error> - top - bottom)) -
						getSum(grid[i], 0, grid[i].length, gap, false);
					if (d != 0) {
						int w = getSum(grid[2 + i], 0, grid[2 + i].length, 0, false);
						if (w > 0) {
							for (int j = 0; j < grid[i].length; j++) {
								if (grid[2 + i][j] != 0) {
									grid[i][j] += d * grid[2 + i][j] / w;
								}
							}
						}
					}
				}

				int i = 0;
				for (Object comp = get(component, "component");
						comp != null; comp = get(comp, ":next")) {
					if (!getBoolean(comp, "visible", true)) { continue; }
					int ix = left + getSum(grid[0], 0, grid[4][i], gap, true);
					int iy = top + getSum(grid[1], 0, grid[5][i], gap, true);
					int iwidth = getSum(grid[0], grid[4][i], grid[6][i], gap, false);
					int iheight = getSum(grid[1], grid[5][i], grid[7][i], gap, false);
					String halign = getString(comp, "halign", "fill");
					String valign = getString(comp, "valign", "fill");
					if ((halign != "fill") || (valign != "fill")) {
						Dimension d = getPreferredSize(comp);
						if (halign != "fill") {
							int dw = Math.max(0, iwidth - d.width);
							if (halign == "center") { ix += dw / 2; }
								else if (halign == "right") { ix += dw; }
							iwidth -= dw;
						}
						if (valign != "fill") {
							int dh = Math.max(0, iheight - d.height);
							if (valign == "center") { iy += dh / 2; }
								else if (valign == "bottom") { iy += dh; }
							iheight -= dh;
						}
					}
					setRectangle(comp, "bounds", ix, iy, iwidth, iheight);
					doLayout(comp);
					i++;
				}
			}
		}
		else if ("desktop" == classname) {
			<error descr="Cannot resolve symbol 'Rectangle'">Rectangle</error> bounds = getRectangle(component, "bounds");
			for (Object comp = get(component, "component");
					comp != null; comp = get(comp, ":next")) {
				String iclass = getClass(comp);
				if (iclass == "dialog") {
					Dimension d = getPreferredSize(comp);
					if (get(comp, "bounds") == null)
					setRectangle(comp, "bounds",
						Math.max(0, (bounds.<error descr="Cannot resolve symbol 'width'">width</error> - d.width) / 2),
						Math.max(0, (bounds.<error descr="Cannot resolve symbol 'height'">height</error> - d.height) / 2),
						Math.min(d.width, bounds.<error descr="Cannot resolve symbol 'width'">width</error>), Math.min(d.height, bounds.<error descr="Cannot resolve symbol 'height'">height</error>));
				} else if ((iclass == "combolist") || (iclass == "popupmenu")) {
						iclass = iclass; //compiler bug
				} else {
					setRectangle(comp, "bounds", 0, 0, bounds.<error descr="Cannot resolve symbol 'width'">width</error>, bounds.<error descr="Cannot resolve symbol 'height'">height</error>);
				}
				doLayout(comp);
			}
		}
		else if ("spinbox" == classname) {
			layoutField(component, block, false, 0);
		}
		else if ("splitpane" == classname) {
			<error descr="Cannot resolve symbol 'Rectangle'">Rectangle</error> bounds = getRectangle(component, "bounds");
			boolean horizontal = ("vertical" != get(component, "orientation"));
			int divider = getInteger(component, "divider", -1);
			int maxdiv = (horizontal ? bounds.<error descr="Cannot resolve symbol 'width'">width</error> : bounds.<error descr="Cannot resolve symbol 'height'">height</error>) - 5;

			Object comp1 = get(component, "component");
			boolean visible1 = (comp1 != null) && getBoolean(comp1, "visible", true);
			if (divider == -1) {
				int d1 = 0;
				if (visible1) {
					Dimension d = getPreferredSize(comp1);
					d1 = horizontal ? d.width : d.height;
				}
				divider = Math.min(d1, maxdiv);
				setInteger(component, "divider", divider, -1);
			}
			else if (divider > maxdiv) {
				setInteger(component, "divider", divider = maxdiv, -1);
			}

			if (visible1) {
				setRectangle(comp1, "bounds", 0, 0, horizontal ? divider : bounds.<error descr="Cannot resolve symbol 'width'">width</error>,
					horizontal ? bounds.<error descr="Cannot resolve symbol 'height'">height</error> : divider);
				doLayout(comp1);
			}
			Object comp2 = (comp1 != null) ? get(comp1, ":next") : null;
			if ((comp2 != null) && getBoolean(comp2, "visible", true)) {
				setRectangle(comp2, "bounds", horizontal ? (divider + 5) : 0,
					horizontal ? 0 : (divider + 5),
					horizontal ? (bounds.<error descr="Cannot resolve symbol 'width'">width</error> - 5 - divider) : bounds.<error descr="Cannot resolve symbol 'width'">width</error>,
					horizontal ? bounds.<error descr="Cannot resolve symbol 'height'">height</error> : (bounds.<error descr="Cannot resolve symbol 'height'">height</error> - 5 - divider));
				doLayout(comp2);
			}
		}
		else if (("list" == classname) ||
				("table" == classname) || ("tree" == classname)) {
			int width = 0;
			int columnheight = 0;
			if ("table" == classname) {
				for (Object column = get(component, "column");
						column != null; column = get(column, ":next")) {
					width += getInteger(column, "width", 80);
					Dimension d = getSize(column, 2, 2, "left");
					columnheight = Math.max(columnheight, d.height);
				}
			}
			String itemname = ("list" == classname) ? "item" :
				(("table" == classname) ? "row" : "node");
			int y = 0;
			int level = 0;
			for (Object item = get(component, itemname); item != null;) {
				int x = 0;
				int iwidth = 0; int iheight = 0;
				if ("table" == classname) {
					iwidth = width;
					for (Object cell = get(item, "cell");
							cell != null; cell = get(cell, ":next")) {
						Dimension d = getSize(cell, 2, 3, "left");
						iheight = Math.max(iheight, d.height);
					}
				}
				else {
					if ("tree" == classname) {
						x = (level + 1) * block;
					}
					Dimension d = getSize(item, 2, 3, "left");
					iwidth = d.width; iheight = d.height;
					width = Math.max(width, x + d.width);
				}
				setRectangle(item, "bounds", x, y, iwidth, iheight);
				y += iheight;
				if ("tree" == classname) {
					Object next = get(item, "node");
					if ((next != null) && getBoolean(item, "expanded", true)) {
						level++;
					} else {
						while (((next = get(item, ":next")) == null) && (level > 0)) {
							item = getParent(item);
							level--;
						}
					}
					item = next;
				} else {
					item = get(item, ":next");
				}
			}
			layoutScrollPane(component, width, y - 1, 0, columnheight);
		}
		else if ("menubar" == classname) {
			<error descr="Cannot resolve symbol 'Rectangle'">Rectangle</error> bounds = getRectangle(component, "bounds");
			int x = 0;
			for (Object menu = get(component, "menu");
					menu != null; menu = get(menu, ":next")) {
				Dimension d = getSize(menu, 8, 4, "left");
				setRectangle(menu, "bounds", x, 0, d.width, bounds.<error descr="Cannot resolve symbol 'height'">height</error>);
				x += d.width;
			}
		}
		else if (("combolist" == classname) || ("popupmenu" == classname)) {
			boolean combo = ("combolist" == classname);
			int pw = 0; int ph = 0; int pxy = combo ? 0 : 1;
			for (Object item = get(get(component, combo ? "combobox" : "menu"),
					combo ? "choice" : "menu"); item != null; item = get(item, ":next")) {
				String itemclass = combo ? null : getClass(item);
				Dimension d = (itemclass == "separator") ? new Dimension(1, 1) :
					getSize(item, 8 , 4, "left");
				if (itemclass == "checkboxmenuitem") {
					d.width = d.width + block + 3;
					d.height = Math.max(block, d.height);
				}
				else if (itemclass == "menu") {
					d.width += block;
				}
				setRectangle(item, "bounds", pxy, pxy + ph, d.width, d.height);
				pw = Math.max(pw, d.width);
				ph += d.height;
			}
			<error descr="Cannot resolve symbol 'Rectangle'">Rectangle</error> r = getRectangle(component, "bounds");
			r.<error descr="Cannot resolve symbol 'width'">width</error> = pw + 2; r.<error descr="Cannot resolve symbol 'height'">height</error> = ph + 2;
			if (combo) {
				<error descr="Cannot resolve symbol 'Rectangle'">Rectangle</error> db = getRectangle(content, "bounds");
				if (r.<error descr="Cannot resolve symbol 'y'">y</error> + ph + 2 > db.<error descr="Cannot resolve symbol 'height'">height</error>) {
					r.<error descr="Cannot resolve symbol 'width'">width</error> = pw + 2 + block;
					r.<error descr="Cannot resolve symbol 'height'">height</error> = db.<error descr="Cannot resolve symbol 'height'">height</error> - r.<error descr="Cannot resolve symbol 'y'">y</error>;
				}
				else {
					r.<error descr="Cannot resolve symbol 'height'">height</error> = Math.min(r.<error descr="Cannot resolve symbol 'height'">height</error>, db.<error descr="Cannot resolve symbol 'height'">height</error> - r.<error descr="Cannot resolve symbol 'y'">y</error>);
				}
				r.<error descr="Cannot resolve symbol 'width'">width</error> = Math.min(r.<error descr="Cannot resolve symbol 'width'">width</error>, db.<error descr="Cannot resolve symbol 'width'">width</error> - r.<error descr="Cannot resolve symbol 'x'">x</error>);
				layoutScrollPane(component, pw, ph, 0, 0);//~
			}
		}
		//java>
		else if ("bean" == classname) {
				<error descr="Cannot resolve symbol 'Rectangle'">Rectangle</error> r = getRectangle(component, "bounds");
				((Component) get(component, "bean")).setBounds(r);
		}
		//<java
	}

	/**
	 *
	 */
	private Object popup(Object component, Object classname) {
		Object popup = null;
		int px = 0; int py = 0;
		if (("menubar" == classname) || ("popupmenu" == classname)) {
			Object popupmenu = get(component, "popupmenu");
			Object selected = get(component, "selected");
			if (popupmenu != null) {
				if (get(popupmenu, "menu") == selected) { return null; }
				set(popupmenu, "selected", null);
				set(popupmenu, "menu", null);
				removeItemImpl(content, "component", popupmenu);
				repaint(popupmenu);
				set(popupmenu, ":parent", null);
				set(component, "popupmenu", null);
				if (mouseinside == popupmenu) {
					findComponent(content, mousex, mousey);
					handleMouseEvent(mousex, mousex, 1, false, false, false, //java
						<error descr="Cannot resolve symbol 'MouseEvent'">MouseEvent</error>.MOUSE_ENTERED, mouseinside, insidepart); //java
				}
				popup(popupmenu, "popupmenu");
			}
			if ((selected == null) || (getClass(selected) != "menu")) { return null; }
			popup = createImpl("popupmenu");
			set(popup, "menu", selected);
			set(component, "popupmenu", popup);

			<error descr="Cannot resolve symbol 'Rectangle'">Rectangle</error> bounds = getRectangle(selected, "bounds");
			if ("menubar" == classname) {
				px = bounds.<error descr="Cannot resolve symbol 'x'">x</error>; py = bounds.<error descr="Cannot resolve symbol 'y'">y</error> + bounds.<error descr="Cannot resolve symbol 'height'">height</error> - 1;
			} else {
				px = bounds.<error descr="Cannot resolve symbol 'x'">x</error> + getRectangle(component, "bounds").<error descr="Cannot resolve symbol 'width'">width</error> - 4;
				py = bounds.<error descr="Cannot resolve symbol 'y'">y</error>;
			}
		}
		else { //if ("combobox" == classname) {
			popup = createImpl("combolist");
			set(popup, "combobox", component);
			set(component, "combolist", popup);

			py = getRectangle(component, "bounds").<error descr="Cannot resolve symbol 'height'">height</error> + 1;
		}
		if (("menubar" == classname) || ("combobox" == classname)) {
			popupowner = component;
		}
		insertItem(content, "component", popup, 0);
		set(popup, ":parent", content);
		while (component != content) {
			<error descr="Cannot resolve symbol 'Rectangle'">Rectangle</error> r = getRectangle(component, "bounds");
			px += r.<error descr="Cannot resolve symbol 'x'">x</error>; py += r.<error descr="Cannot resolve symbol 'y'">y</error>;
			component = getParent(component);
		}
		setRectangle(popup, "bounds", px, py, 0, 0);
		doLayout(popup); repaint(popup);
		return popup;
	}

	/**
	 *
	 */
	private void closeup(Object combobox, Object combolist, Object item) {
		if ((item != null) && getBoolean(item, "enabled", true)) {
			String text = getString(item, "text", "");
			set(combobox, "text", text); // if editable
			setInteger(combobox, "start", text.length(), 0);
			setInteger(combobox, "end", 0, 0);
			set(combobox, "icon", get(item, "icon"));
			validate(combobox);
			setInteger(combobox, "selected", getIndex(combobox, "choice", item), -1);
			invoke(combobox, "action");
		}
		set(combolist, "combobox", null);
		set(combobox, "combolist", null);
		removeItemImpl(content, "component", combolist);
		repaint(combolist);
		set(combolist, ":parent", null);
		popupowner = null;
		if (mouseinside == combolist) {
			findComponent(content, mousex, mousey);
			handleMouseEvent(mousex, mousex, 1, false, false, false, //java
				<error descr="Cannot resolve symbol 'MouseEvent'">MouseEvent</error>.MOUSE_ENTERED, mouseinside, insidepart); //java
		}
	}

	/**
	 *
	 */
	private void closeup(Object menubar) {
		set(menubar, "selected", null);
		popup(menubar, "menubar");
		repaint(menubar); // , selected
		popupowner = null;
	}

	/**
	 *
	 */
	private void closeup() {
		if (popupowner != null) {
			String classname = getClass(popupowner);
			if ("menubar" == classname) {
				closeup(popupowner);
			}
			else if ("combobox" == classname) {
				closeup(popupowner, get(popupowner, "combolist"), null);
			}
		}
	}

	/**
	 *
	 */
	private void showTip() {
		String text = null;
		tooltipowner = null;
		String classname = getClass(mouseinside);
		if ((classname == "tabbedpane") || (classname == "menubar") || (classname == "popupmenu")) {
			if (insidepart != null) {
				text = getString(insidepart, "tooltip", null);
			}
		}
		else if (classname == "combolist") {
			if (insidepart instanceof Object[]) {
				text = getString(insidepart, "tooltip", null);
			}
		}
		//list table tree
		if (text == null) { text = getString(mouseinside, "tooltip", null); }
			else { tooltipowner = insidepart; }
		if (text != null) {
			<error descr="Cannot resolve symbol 'FontMetrics'">FontMetrics</error> fm = getFontMetrics(getFont());
			int width = fm.<error descr="Cannot resolve method 'stringWidth(String)'">stringWidth</error>(text) + 4;
			int height = fm.<error descr="Cannot resolve method 'getAscent()'">getAscent</error>() + fm.<error descr="Cannot resolve method 'getDescent()'">getDescent</error>() + 4;
			if (tooltipowner == null) { tooltipowner = mouseinside; }
			setRectangle(tooltipowner, "tooltipbounds", mousex + 10, mousey + 10, width, height);
			repaint(mousex + 10, mousey + 10, width, height);
		}
	}

	/**
	 *
	 */
	private void hideTip() {
		if (tooltipowner != null) {
			<error descr="Cannot resolve symbol 'Rectangle'">Rectangle</error> bounds = getRectangle(tooltipowner, "tooltipbounds");
			set(tooltipowner, "tooltipbounds", null);
			tooltipowner = null;
			repaint(bounds.<error descr="Cannot resolve symbol 'x'">x</error>, bounds.<error descr="Cannot resolve symbol 'y'">y</error>, bounds.<error descr="Cannot resolve symbol 'width'">width</error>, bounds.<error descr="Cannot resolve symbol 'height'">height</error>);
		}
	}

	/**
	 *
	 */
	private void layoutField(Object component, int dw, boolean hidden, int left) {
		int width = getRectangle(component, "bounds").<error descr="Cannot resolve symbol 'width'">width</error> - left -dw;
		String text = getString(component, "text", "");
		int start = getInteger(component, "start", 0);
		if (start > text.length()) { setInteger(component, "start", start = text.length(), 0); }
		int end = getInteger(component, "end", 0);
		if (end > text.length()) { setInteger(component, "end", end = text.length(), 0); }
		int offset = getInteger(component, "offset", 0);
		int off = offset;
		<error descr="Cannot resolve symbol 'FontMetrics'">FontMetrics</error> fm = getFontMetrics(getFont());
		int caret = hidden ? (fm.<error descr="Cannot resolve method 'charWidth(char)'">charWidth</error>('*') * end) :
			fm.<error descr="Cannot resolve method 'stringWidth(String)'">stringWidth</error>(text.substring(0, end)); //java
			//midp font.substringWidth(text, 0, end);
		if (off > caret) {
			off = caret;
		}
		else if (off < caret - width + 4) {
			off = caret - width + 4;
		}
		off = Math.max(0, Math.min(off, (hidden ? (fm.<error descr="Cannot resolve method 'charWidth(char)'">charWidth</error>('*') *
			text.length()) : fm.<error descr="Cannot resolve method 'stringWidth(String)'">stringWidth</error>(text)) - width + 4));
		if (off != offset) {
			setInteger(component, "offset", off, 0);
		}
	}

	/**
	 *
	 */
	private void layoutScrollPane(Object component,
			int contentwidth, int contentheight, int rowwidth, int columnheight) {
		<error descr="Cannot resolve symbol 'Rectangle'">Rectangle</error> bounds = getRectangle(component, "bounds");
		boolean hneed = false; boolean vneed = false;
		if (contentwidth > bounds.<error descr="Cannot resolve symbol 'width'">width</error> - rowwidth - 2) {
			hneed = true;
			vneed = (contentheight > bounds.<error descr="Cannot resolve symbol 'height'">height</error> - columnheight - 2 - block);
		}
		if (vneed || (contentheight > bounds.<error descr="Cannot resolve symbol 'height'">height</error> - columnheight - 2)) {
			vneed = true;
			hneed = hneed || (contentwidth > bounds.<error descr="Cannot resolve symbol 'width'">width</error> - rowwidth - 2 - block);
		}
		int viewportwidth = bounds.<error descr="Cannot resolve symbol 'width'">width</error> - rowwidth - (vneed ? block : 0);
		int viewportheight = bounds.<error descr="Cannot resolve symbol 'height'">height</error> - columnheight - (hneed ? block : 0);
		setRectangle(component, ":port",
			rowwidth, columnheight, viewportwidth, viewportheight); //?rowwidth

		<error descr="Cannot resolve symbol 'Rectangle'">Rectangle</error> view = getRectangle(component, ":view");
		setRectangle(component, ":view",
			(view != null) ? Math.max(0,
				Math.min(view.<error descr="Cannot resolve symbol 'x'">x</error>, contentwidth - viewportwidth + 2)) : 0,
			(view != null) ? Math.max(0,
				Math.min(view.<error descr="Cannot resolve symbol 'y'">y</error>, contentheight - viewportheight + 2)) : 0,
			Math.max(viewportwidth - 2, contentwidth),
			Math.max(viewportheight - 2, contentheight));
	}

	/**
	 *
	 */
	private void scrollToVisible(Object component,
			int x, int y, int width, int height) {
		<error descr="Cannot resolve symbol 'Rectangle'">Rectangle</error> view = getRectangle(component, ":view");
		<error descr="Cannot resolve symbol 'Rectangle'">Rectangle</error> port = getRectangle(component, ":port");
		int vx = Math.max(x + width - port.<error descr="Cannot resolve symbol 'width'">width</error> + 2, Math.min(view.<error descr="Cannot resolve symbol 'x'">x</error>, x));
		int vy = Math.max(y + height - port.<error descr="Cannot resolve symbol 'height'">height</error> + 2, Math.min(view.<error descr="Cannot resolve symbol 'y'">y</error>, y));
		if ((view.<error descr="Cannot resolve symbol 'x'">x</error> != vx) || (view.<error descr="Cannot resolve symbol 'y'">y</error> != vy)) {
			repaint(component); // horizontal | vertical
			view.<error descr="Cannot resolve symbol 'x'">x</error> = vx; view.<error descr="Cannot resolve symbol 'y'">y</error> = vy;
		}
	}

	/**
	 *
	 */
	public Dimension getPreferredSize() {
		return getPreferredSize(content);
	}

	/**
	 *
	 */
	private Dimension getPreferredSize(Object component) {
		int width = getInteger(component, "width", 0);
		int height = getInteger(component, "height", 0);
		if ((width > 0) && (height > 0)) {
			return new Dimension(width, height);
		}
		String classname = getClass(component);
		//System.out.println("classname: " + classname);
		if ("label" == classname) {
			return getSize(component, 0, 0, "left");
		}
		if ("button" == classname) {
			return getSize(component, 12, 6, "center");
		}
		if ("checkbox" == classname) {
			Dimension d = getSize(component, 0, 0, "left");
			d.width = d.width + block + 3;
