/* D-RexGxt - D-RexGxt - GUI Design Tool for GWT
 * Copyright (c) 2008,  KPS Corporation
 * All rights reserved.
 *
 * Open Source License
 * ------------------------------------------------------------------------------------------
 * D-RexGxt is licensed under the terms of the Open Source GPL 3.0 license.
 *
 * http://www.gnu.org/licenses/gpl.html
 *
 * --
 *
 * 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
 * General Public License for more details.
 */
package jp.co.kpscorp.gwt.client.design.gxt;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import com.extjs.gxt.ui.client.Events;
import com.extjs.gxt.ui.client.Style.HorizontalAlignment;
import com.extjs.gxt.ui.client.Style.LayoutRegion;
import com.extjs.gxt.ui.client.Style.Orientation;
import com.extjs.gxt.ui.client.Style.Scroll;
import com.extjs.gxt.ui.client.Style.VerticalAlignment;
import com.extjs.gxt.ui.client.data.BaseModelData;
import com.extjs.gxt.ui.client.data.ModelData;
import com.extjs.gxt.ui.client.store.ListStore;
import com.extjs.gxt.ui.client.util.Margins;
import com.extjs.gxt.ui.client.util.Point;
import com.extjs.gxt.ui.client.util.Rectangle;
import com.extjs.gxt.ui.client.util.Size;
import com.extjs.gxt.ui.client.widget.BoxComponent;
import com.extjs.gxt.ui.client.widget.Component;
import com.extjs.gxt.ui.client.widget.Container;
import com.extjs.gxt.ui.client.widget.ContentPanel;
import com.extjs.gxt.ui.client.widget.Layout;
import com.extjs.gxt.ui.client.widget.LayoutContainer;
import com.extjs.gxt.ui.client.widget.Shadow.ShadowPosition;
import com.extjs.gxt.ui.client.widget.button.Button;
import com.extjs.gxt.ui.client.widget.button.ButtonBar;
import com.extjs.gxt.ui.client.widget.form.CheckBox;
import com.extjs.gxt.ui.client.widget.form.ComboBox;
import com.extjs.gxt.ui.client.widget.form.Field;
import com.extjs.gxt.ui.client.widget.form.TextField;
import com.extjs.gxt.ui.client.widget.form.ComboBox.TriggerAction;
import com.extjs.gxt.ui.client.widget.form.FormPanel.LabelAlign;
import com.extjs.gxt.ui.client.widget.layout.AbsoluteData;
import com.extjs.gxt.ui.client.widget.layout.AbsoluteLayout;
import com.extjs.gxt.ui.client.widget.layout.AccordionLayout;
import com.extjs.gxt.ui.client.widget.layout.AnchorData;
import com.extjs.gxt.ui.client.widget.layout.AnchorLayout;
import com.extjs.gxt.ui.client.widget.layout.BorderLayout;
import com.extjs.gxt.ui.client.widget.layout.BorderLayoutData;
import com.extjs.gxt.ui.client.widget.layout.CardLayout;
import com.extjs.gxt.ui.client.widget.layout.CenterLayout;
import com.extjs.gxt.ui.client.widget.layout.ColumnData;
import com.extjs.gxt.ui.client.widget.layout.ColumnLayout;
import com.extjs.gxt.ui.client.widget.layout.FillData;
import com.extjs.gxt.ui.client.widget.layout.FillLayout;
import com.extjs.gxt.ui.client.widget.layout.FitData;
import com.extjs.gxt.ui.client.widget.layout.FitLayout;
import com.extjs.gxt.ui.client.widget.layout.FlowData;
import com.extjs.gxt.ui.client.widget.layout.FlowLayout;
import com.extjs.gxt.ui.client.widget.layout.FormData;
import com.extjs.gxt.ui.client.widget.layout.FormLayout;
import com.extjs.gxt.ui.client.widget.layout.LayoutData;
import com.extjs.gxt.ui.client.widget.layout.MarginData;
import com.extjs.gxt.ui.client.widget.layout.RowData;
import com.extjs.gxt.ui.client.widget.layout.RowLayout;
import com.extjs.gxt.ui.client.widget.layout.TableData;
import com.extjs.gxt.ui.client.widget.layout.TableLayout;
import com.extjs.gxt.ui.client.widget.layout.TableRowLayout;
import com.extjs.gxt.ui.client.widget.tree.Tree;
import com.google.gwt.core.client.GWT;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.i18n.client.NumberFormat;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.ui.CellPanel;
import com.google.gwt.user.client.ui.Widget;

import jp.co.kpscorp.gwt.client.design.DesignPanel;

import jp.co.kpscorp.gwt.client.design.WidgetService;
import jp.co.kpscorp.gwt.client.design.WidgetServiceFactory;
import jp.co.kpscorp.gwt.client.design.WidgetServiceWrapper;
import jp.co.kpscorp.gwt.client.design.delegate.Delegate;
import jp.co.kpscorp.gwt.client.design.gxt.service.layout.WsLayout;
import jp.co.kpscorp.gwt.client.design.gxt.widget.AbsoluteDataWidget;
import jp.co.kpscorp.gwt.client.design.gxt.widget.AbsoluteLayoutWidget;
import jp.co.kpscorp.gwt.client.design.gxt.widget.AccordionLayoutWidget;
import jp.co.kpscorp.gwt.client.design.gxt.widget.AnchorDataWidget;
import jp.co.kpscorp.gwt.client.design.gxt.widget.AnchorLayoutWidget;
import jp.co.kpscorp.gwt.client.design.gxt.widget.BorderLayoutDataWidget;
import jp.co.kpscorp.gwt.client.design.gxt.widget.BorderLayoutWidget;
import jp.co.kpscorp.gwt.client.design.gxt.widget.CardLayoutWidget;
import jp.co.kpscorp.gwt.client.design.gxt.widget.CenterLayoutWidget;
import jp.co.kpscorp.gwt.client.design.gxt.widget.ColumnDataWidget;
import jp.co.kpscorp.gwt.client.design.gxt.widget.ColumnLayoutWidget;
import jp.co.kpscorp.gwt.client.design.gxt.widget.ConfigWidget;
import jp.co.kpscorp.gwt.client.design.gxt.widget.FillDataWidget;
import jp.co.kpscorp.gwt.client.design.gxt.widget.FillLayoutWidget;
import jp.co.kpscorp.gwt.client.design.gxt.widget.FitDataWidget;
import jp.co.kpscorp.gwt.client.design.gxt.widget.FitLayoutWidget;
import jp.co.kpscorp.gwt.client.design.gxt.widget.FlowDataWidget;
import jp.co.kpscorp.gwt.client.design.gxt.widget.FlowLayoutWidget;
import jp.co.kpscorp.gwt.client.design.gxt.widget.FormDataWidget;
import jp.co.kpscorp.gwt.client.design.gxt.widget.FormLayoutWidget;
import jp.co.kpscorp.gwt.client.design.gxt.widget.LayoutDataWidget;
import jp.co.kpscorp.gwt.client.design.gxt.widget.LayoutWidget;
import jp.co.kpscorp.gwt.client.design.gxt.widget.MarginDataWidget;
import jp.co.kpscorp.gwt.client.design.gxt.widget.RowDataWidget;
import jp.co.kpscorp.gwt.client.design.gxt.widget.RowLayoutWidget;
import jp.co.kpscorp.gwt.client.design.gxt.widget.TableDataWidget;
import jp.co.kpscorp.gwt.client.design.gxt.widget.TableLayoutWidget;
import jp.co.kpscorp.gwt.client.design.gxt.widget.TableRowLayoutWidget;

public class GxtUtil {
	public static final Scroll[] scrolls = new Scroll[] { Scroll.ALWAYS,
			Scroll.AUTO, Scroll.AUTOX, Scroll.AUTOY, Scroll.NONE };

	public static final Orientation[] orientations = new Orientation[] {
			Orientation.HORIZONTAL, Orientation.VERTICAL };

	public static final HorizontalAlignment[] horizontalAlignments = new HorizontalAlignment[] {
			HorizontalAlignment.CENTER, HorizontalAlignment.LEFT,
			HorizontalAlignment.RIGHT };

	public static final VerticalAlignment[] verticalAlignments = new VerticalAlignment[] {
			VerticalAlignment.BOTTOM, VerticalAlignment.MIDDLE,
			VerticalAlignment.TOP };

	public static final LabelAlign[] labelAligns = new LabelAlign[] {
			LabelAlign.LEFT, LabelAlign.RIGHT, LabelAlign.TOP };

	public static final LayoutRegion[] layoutRegion = new LayoutRegion[] {
			LayoutRegion.CENTER, LayoutRegion.EAST, LayoutRegion.NORTH,
			LayoutRegion.SOUTH, LayoutRegion.WEST };

	public static final ShadowPosition[] shadowPosition = new ShadowPosition[] {
			ShadowPosition.DROP, ShadowPosition.FRAME, ShadowPosition.SIDES };

	public static final TriggerAction[] triggerAction = new TriggerAction[] {
			TriggerAction.ALL, TriggerAction.QUERY };

	public static final Object[][] enums = { scrolls, orientations,
			horizontalAlignments, verticalAlignments, labelAligns,
			layoutRegion, shadowPosition, triggerAction };

	public static String[] add(String[] s1, String[] s2) {
		String[] ss = new String[s1.length + s2.length];
		for (int i = 0; i < s1.length; i++) {
			ss[i] = s1[i];
		}
		for (int i = 0; i < s2.length; i++) {
			ss[s1.length + i] = s2[i];
		}
		return ss;
	}

	public static String[] addAndRemove(String[] s1, String[] s2,
			String[] remove) {
		List<String> l = new ArrayList<String>();
		for (int i = 0; i < s1.length; i++) {
			if (!GxtUtil.contains(remove, s1[i])) {
				l.add(s1[i]);
			}
		}
		for (int i = 0; i < s2.length; i++) {
			if (!GxtUtil.contains(remove, s2[i])) {
				l.add(s2[i]);
			}
		}
		String[] ss = l.toArray(new String[1]);
		return ss;
	}

	public static Field<? extends Object> getLtext(Delegate del, String prop) {
		Object o = del.exec(GxtUtil.makeGetterName(prop), null);
		if (o == null) {
			o = del.exec(GxtUtil.makeGetterName(prop, true), null);
			if (o == null) {
				o = "<null>";
			}
		}
		Field<? extends Object> lt;
		int inx;
		if (o instanceof Boolean) {
			Boolean b = (Boolean) o;
			CheckBox cb = new CheckBox();
			cb.setFieldLabel(prop);
			cb.setValue(b.booleanValue());
			lt = cb;
		} else if ((inx = getEnum(o, prop)) != -1) {
			lt = getLtext(del, prop, enums[inx]);
		} else {
			TextField<String> tf = new TextField<String>();
			tf.setFieldLabel(prop);
			lt = tf;
			if (o instanceof Rectangle) {
				Rectangle r = (Rectangle) o;
				tf.setValue(r.x + "," + r.y + "," + r.width + "," + r.height);
			} else if (o instanceof Margins) {
				Margins r = (Margins) o;
				tf.setValue(r.top + "," + r.left + "," + r.bottom + ","
						+ r.right);
			} else if (o instanceof Point) {
				Point r = (Point) o;
				tf.setValue(r.x + "," + r.y);
			} else if (o instanceof Size) {
				Size r = (Size) o;
				tf.setValue(r.width + "," + r.height);
			} else if (o instanceof NumberFormat) {
				NumberFormat r = (NumberFormat) o;
				tf.setValue(r.getPattern());
			} else if (o instanceof DateTimeFormat) {
				DateTimeFormat r = (DateTimeFormat) o;
				tf.setValue(r.getPattern());
			} else {
				tf.setValue(o.toString());
			}
		}
		return lt;
	}

	private static int getEnum(Object o, String prop) {
		String cname = prop.substring(0, 1).toUpperCase() + prop.substring(1);
		Class<? extends Object> c = o.getClass();
		for (int i = 0; i < enums.length; i++) {
			Object[] enm = enums[i];
			if (enm[0].getClass().equals(c)) {
				return i;
			}
			if ("<null>".equals(o.toString())) {
				String ename = GxtUtil.getSimpleName(enm[0].getClass());
				ename = ename.substring(ename.indexOf('$') + 1);
				ename = ename.replace("Alignment", "Align");
				if (cname.indexOf(ename) != -1) {
					return i;
				}
			}
		}
		return -1;
	}

	public static ComboBox<ModelData> getLtext(Delegate del, String prop,
			Object[] sel) {
		Object o = del.exec(GxtUtil.makeGetterName(prop), null);
		int i = GxtUtil.getIdex(sel, o);
		ComboBox<ModelData> select = makeListBox(sel, prop);
		if (i != -1) {
			select.setValue(select.getStore().getAt(i));
		}
		return select;

	}

	public static ComboBox<ModelData> makeListBox(Object[] os, String prop) {
		ComboBox<ModelData> select = new ComboBox<ModelData>();
		select.setFieldLabel(prop);
		select.setDisplayField("label");
		select.setEditable(false);
		List<ModelData> l = new ArrayList<ModelData>();
		for (int i = 0; i < os.length; i++) {
			BaseModelData model = new BaseModelData();
			model.set("label", os[i].toString());
			model.set("value", os[i]);
			l.add(model);
		}
		ListStore<ModelData> ls = new ListStore<ModelData>();
		ls.add(l);
		select.setStore(ls);
		return select;
	}

	public static void setLtext(Delegate del, String prop, Field ltext) {
		Object val = ltext.getValue();
		if (val instanceof BaseModelData) {
			BaseModelData data = (BaseModelData) val;
			val = data.get("value");
		}
		if ("<null>".equals(val)) {
			val = null;
		} else if ("<setter only>".equals(val)) {
			return;
		}
		del.exec(GxtUtil.makeSetterName(prop), new Object[] { val });
	}

	public static Rectangle makeRectangle(String s) {
		List l = GxtUtil.devideStr(s, ',');
		int[] is = new int[] { 0, 0, 0, 0 };
		for (int i = 0; i < l.size() && i < is.length; i++) {
			is[i] = GxtUtil.safeParse(l.get(i));
		}
		return new Rectangle(is[0], is[1], is[2], is[3]);
	}

	public static Margins makeMargins(String s) {
		List l = GxtUtil.devideStr(s, ',');
		int[] is = new int[] { 0, 0, 0, 0 };
		for (int i = 0; i < l.size() && i < is.length; i++) {
			is[i] = GxtUtil.safeParse(l.get(i));
		}
		return new Margins(is[0], is[1], is[2], is[3]);
	}

	public static Point makePoint(String s) {
		List l = GxtUtil.devideStr(s, ',');
		int[] is = new int[] { 0, 0 };
		for (int i = 0; i < l.size() && i < is.length; i++) {
			is[i] = GxtUtil.safeParse(l.get(i));
		}
		return new Point(is[0], is[1]);
	}

	public static Size makeSize(String s) {
		List l = GxtUtil.devideStr(s, ',');
		int[] is = new int[] { 0, 0 };
		for (int i = 0; i < l.size() && i < is.length; i++) {
			is[i] = GxtUtil.safeParse(l.get(i));
		}
		return new Size(is[0], is[1]);
	}

	public static DateTimeFormat makeDateTimeFormat(String s) {
		return DateTimeFormat.getFormat(s);
	}

	public static NumberFormat makeNumberFormat(String s) {
		return NumberFormat.getFormat(s);
	}

	public static LayoutWidget getLayoutWidget(Layout layout,
			LayoutContainer container) {
		if (layout instanceof FormLayout) {
			return new FormLayoutWidget((FormLayout) layout, container);
		} else if (layout instanceof AbsoluteLayout) {
			return new AbsoluteLayoutWidget((AbsoluteLayout) layout, container);
		} else if (layout instanceof AccordionLayout) {
			return new AccordionLayoutWidget((AccordionLayout) layout,
					container);
		} else if (layout instanceof CardLayout) {
			return new CardLayoutWidget((CardLayout) layout, container);
		} else if (layout instanceof FillLayout) {
			return new FillLayoutWidget((FillLayout) layout, container);
		} else if (layout instanceof TableRowLayout) {
			return new TableRowLayoutWidget((TableRowLayout) layout, container);
		} else if (layout instanceof BorderLayout) {
			return new BorderLayoutWidget((BorderLayout) layout, container);
		} else if (layout instanceof CenterLayout) {
			return new CenterLayoutWidget((CenterLayout) layout, container);
		} else if (layout instanceof ColumnLayout) {
			return new ColumnLayoutWidget((ColumnLayout) layout, container);
		} else if (layout instanceof FitLayout) {
			return new FitLayoutWidget((FitLayout) layout, container);
		} else if (layout instanceof FlowLayout) {
			return new FlowLayoutWidget((FlowLayout) layout, container);
		} else if (layout instanceof RowLayout) {
			return new RowLayoutWidget((RowLayout) layout, container);
		} else if (layout instanceof TableLayout) {
			return new TableLayoutWidget((TableLayout) layout, container);
		} else if (layout instanceof AnchorLayout) {
			return new AnchorLayoutWidget((AnchorLayout) layout, container);
		}
		return null;
	}

	public static LayoutDataWidget getLayoutDataWidget(LayoutData data,
			Component parent) {
		if (data instanceof AbsoluteData) {
			return new AbsoluteDataWidget((AbsoluteData) data, parent);
		} else if (data instanceof FormData) {
			return new FormDataWidget((FormData) data, parent);
		} else if (data instanceof AnchorData) {
			return new AnchorDataWidget((AnchorData) data, parent);
		} else if (data instanceof FillData) {
			return new FillDataWidget((FillData) data, parent);
		} else if (data instanceof FitData) {
			return new FitDataWidget((FitData) data, parent);
		} else if (data instanceof FlowData) {
			return new FlowDataWidget((FlowData) data, parent);
		} else if (data instanceof RowData) {
			return new RowDataWidget((RowData) data, parent);
		} else if (data instanceof BorderLayoutData) {
			return new BorderLayoutDataWidget((BorderLayoutData) data, parent);
		} else if (data instanceof ColumnData) {
			return new ColumnDataWidget((ColumnData) data, parent);
		} else if (data instanceof MarginData) {
			return new MarginDataWidget((MarginData) data, parent);
		} else if (data instanceof TableData) {
			return new TableDataWidget((TableData) data, parent);
		}
		return null;
	}

	public static Component resetToParent2(Component removeW, Component parent,
			Component widget) {
		if (parent == null) {
			parent = WidgetServiceFactory.getService(removeW).getParent();
		}
		WidgetService pws = WidgetServiceFactory.getService(parent);
		if (parent instanceof ButtonBar) {
			ButtonBar co = (ButtonBar) parent;
			int i = indexOf(co, removeW);
			co.remove((Button) removeW);
			co.insert((Button) widget, i);
		} else {
			pws.setTargetInfo(parent, removeW);
			pws.removeWidget(removeW);
			pws.addWidget(widget);
		}
		return widget;
	}

	public static int indexOf(Container co, Component w) {
		Iterator it = co.iterator();
		int i = 0;
		while (it.hasNext()) {
			Widget ew = (Widget) it.next();
			if (ew == w || GxtUtil.isIdEquals(ew, w)) {
				return i;
			}
			i++;
		}
		return i;
	}

	public static Component getClone(Component widget) {
		if (widget instanceof Tree) {
			// Treeは逆順でclone作成
			return getClone2(widget);
		}
		Component clone = GxtUtil.getShallowCopy(widget);
		WidgetService clws = WidgetServiceFactory.getService(clone);
		Iterator it = null;
		Component hw = (Component) widget;
		it = GxtUtil.childrenIterator(hw);
		while (it.hasNext()) {
			Component cw = (Component) it.next();
			WidgetService cwws = WidgetServiceFactory.getService(cw);
			if (cwws == null) {
				if (cw != null) {
					System.out.println(cw.getClass().getName()
							+ ":WidgetService not foud !");
				}
			} else {
				Component cclone;
				cclone = cwws.getClone();
				if (cclone != null) {
					clws.setTargetInfo(widget, cw);
					clws.addWidget(cclone);
				}
			}
		}
		return clone;
	}

	public static Component findParent(Component comp) {
		return findParentFromComp(DesignPanel.getInstance().getBasePanel(),
				comp);
	}

	public static Component findParentFromComp(Component parent, Component comp) {
		Iterator it = WidgetServiceFactory.getService(parent)
				.childrenIterator();
		if (it != null) {
			while (it.hasNext()) {
				Component ew = (Component) it.next();
				if (ew == comp) {
					return parent;
				}
				Component cp = findParentFromComp(ew, comp);
				if (cp != null) {
					return cp;
				}
			}
		}
		return null;
	}

	public static Iterator childrenIterator(Component comp) {
		WidgetService c = WidgetServiceFactory.getService(comp);
		if (c == null) {
			return null;
		}
		return c.childrenIterator();
	}

	public static Object getEnumObj(String s) {
		int pi = s.indexOf('.');
		if (pi == -1) {
			return s;
		}
		String cn = s.substring(0, pi);
		for (int i = 0; i < enums.length; i++) {
			Object[] enm = enums[i];
			if (enm[0].getClass().getName().indexOf(cn) != -1) {
				for (int j = 0; j < enm.length; j++) {
					Object o = enm[j];
					if (s.indexOf(o.toString()) != -1) {
						return o;
					}
				}
			}
		}
		return s;
	}

	public static Component getClone2(Component widget) {
		return getClone2(widget, null);
	}

	private static Component getClone2(Component widget, Component parent) {
		Component clone = GxtUtil.getShallowCopy(widget);
		if (clone == null) {
			return null;
		}
		WidgetService pws = WidgetServiceFactory.getService(parent);
		if (pws != null) {
			pws.setTargetInfo(parent, widget);
			pws.addWidget(clone);
		}
		if (clone instanceof Component) {
			Component hw = (Component) widget;
			Iterator it = GxtUtil.childrenIterator(hw);
			while (it.hasNext()) {
				Component cw = (Component) it.next();
				getClone2(cw, clone);
			}
		}
		return clone;
	}

	public static Component fitLayoutData(LayoutContainer container,
			Component comp) {
		WsLayout wl = getWsLayout(container.getLayout(), container);
		if (wl == null) {
			return null;
		}
		wl.resetLayoutWhenAdd(comp);
		return comp;
	}

	private static WsLayout getWsLayout(Layout layout, LayoutContainer container) {
		if (layout == null) {
			return null;
		}
		LayoutWidget lw = getLayoutWidget(layout, container);
		WidgetService ws = WidgetServiceFactory.getService(lw);
		if (ws instanceof WidgetServiceWrapper) {
			WidgetServiceWrapper wsw = (WidgetServiceWrapper) ws;
			ws = wsw.getWrapWidgetService();
		}
		WsLayout wl = (WsLayout) ws;
		return wl;
	}

	public static <C extends Component> C addRender(C comp) {
		if (comp == null) {
			return null;
		}
		if (comp instanceof ConfigWidget) {
			return comp;
		}
		DesignPanel dp = DesignPanel.getInstance();
		// comp.removeListener(Events.Render, dp);
		comp.addListener(Events.Render, dp);
		WidgetService ws = WidgetServiceFactory.getService(comp);
		if (ws != null) {
			Iterator<Component> it = ws.childrenIterator();
			while (it.hasNext()) {
				addRender(it.next());
			}
		}
		return comp;
	}

	public static ContentPanel addButtonAfterRender(ContentPanel comp,
			Button button, int index) {
		if (index == -1) {
			index = comp.getButtonBar().getItemCount();
		}
		WidgetService ws = WidgetServiceFactory.getService(comp);
		ContentPanel cl = (ContentPanel) ws.getClone();
		cl.getButtonBar().setAutoWidth(true);
		cl.getButtonBar().insert(button, index);
		GxtUtil.resetToParent2(comp, (Component) comp.getParent(), cl);
		Component parent = (Component) cl.getParent();
		if (parent instanceof LayoutContainer) {
			LayoutContainer lc = (LayoutContainer) parent;
			lc.layout();
		}
		return cl;
	}

	public static Component addAfterRender(Component parent, Component comp) {
		WidgetService pws = WidgetServiceFactory.getService(parent);
		Component pclone = pws.getClone();
		WidgetServiceFactory.getService(pclone).addWidget(comp);
		GxtUtil.resetToParent2(parent, pws.getParent(), pclone);
		return pclone;
	}

	public static Component removeAfterRender(Component parent, Component comp) {
		WidgetService pws = WidgetServiceFactory.getService(parent);
		Component pclone = pws.getClone();
		pclone = WidgetServiceFactory.getService(pclone).removeWidget(comp);
		GxtUtil.resetToParent2(parent, pws.getParent(), pclone);
		return pclone;
	}

	public static String getAddCode4Adapter(List<String>[] lists,
			String parentFiledName, String fieldName, Map<Object, Object> map,
			String tag) {
		List<String> l = (List<String>) map.get(parentFiledName + "_" + tag);
		String s = l.remove(0);
		l.add(0, s.replaceAll("%1", fieldName));
		lists[1].addAll(l);
		return null;
	}

	public static LayoutData getValidLayoutData(Layout layout) {
		WsLayout wl = getWsLayout(layout, null);
		return wl.getValidLayoutData();
	}

	public static String getSimpleName(Class<? extends Object> clazz) {
		String s = clazz.getName();
		return s.substring(s.lastIndexOf('.') + 1);
	}

	/**
	 * 文字列内の特殊文字をエスケープシーケンスに変換する。 <br>
	 * 対象の特殊文字は\\,\n,\r,\f,\t,\',\"
	 *
	 * @param s
	 * @return
	 */
	public static String escapeString(String s) {
		String res = s;
		res = res.replaceAll("\\\\", "\\\\\\\\");
		res = res.replaceAll("\n", "\\\\n");
		res = res.replaceAll("\r", "\\\\r");
		res = res.replaceAll("\f", "\\\\f");
		res = res.replaceAll("\t", "\\\\t");
		res = res.replaceAll("\'", "\\\\'");
		res = res.replaceAll("\"", "\\\\\"");
		return res;
	}

	/**
	 * 文字列内のエスケープシーケンスを特殊文字にもどす。 <br>
	 * 対象の特殊文字は\\,\n,\r,\f,\t,\',\"
	 *
	 * @param s
	 * @return
	 */
	public static String deescapeString(String s) {
		String res = s;
		res = res.replaceAll("\\\\\\\\", "\\\\");
		res = res.replaceAll("\\\\n", "\n");
		res = res.replaceAll("\\\\r", "\r");
		res = res.replaceAll("\\\\f", "\f");
		res = res.replaceAll("\\\\t", "\t");
		res = res.replaceAll("\\\\'", "\'");
		res = res.replaceAll("\\\\\"", "\"");
		return res;
	}

	public static Component replaceStyleName(Component comp, String styleName) {
		if (styleName != null) {
			List<String> lstyle = new ArrayList<String>();
			String[] sstyle = styleName.trim().replaceAll("\\s", ",").split(
					",", -1);
			for (int i = 0; i < sstyle.length; i++) {
				if (!("".equals(sstyle[i]))) {
					if (!(lstyle.contains(sstyle[i]))) {
						lstyle.add(sstyle[i]);
					}
				}
			}
			StringBuffer sb = new StringBuffer();
			Iterator<String> it = lstyle.iterator();
			while (it.hasNext()) {
				String astyle = it.next();
				sb.append(astyle);
				sb.append(" ");
			}
			comp.setStyleName(sb.toString().trim());
		}
		return comp;
	}

	public static String getHeight(Component widget) {
		return DOM.getStyleAttribute(widget.getElement(), "height");
	}

	public static String getWidth(Component widget) {
		return DOM.getStyleAttribute(widget.getElement(), "width");
	}

	public static boolean isAddable(Component parent, Component widget) {
		if (!isAddable(parent)) {
			return false;
		}
		WidgetService ws = WidgetServiceFactory.getService(widget);
		if (ws != null) {
			return ws.isAddableToParent(parent);
		}
		return false;
	}

	public static boolean isAddable(Component parent) {
		if (!DesignPanel.getInstance().isAddable()) {
			return false;
		}
		WidgetService pws = WidgetServiceFactory.getService(parent);
		if (pws != null) {
			return pws.isAddable();
		}
		return false;
	}

	public static int getIdex(Object[] os, Object o) {
		for (int i = 0; i < os.length; i++) {
			if (o == null) {
				if (os[i] == null) {
					return i;
				}
			} else if (o.equals(os[i])) {
				return i;
			}
		}
		return -1;
	}

	public static int safeParse(Object s) {
		if (s instanceof Integer) {
			Integer ig = (Integer) s;
			return ig.intValue();
		}
		int i = 0;
		try {
			i = Integer.parseInt((String) s);
		} catch (Exception e) {
		}
		return i;
	}

	public static Integer safeParseInteger(Object s) {
		if (s instanceof Integer) {
			Integer ig = (Integer) s;
			return ig;
		}
		Integer i = null;
		try {
			i = new Integer((String) s);
		} catch (Exception e) {
		}
		return i;
	}

	public static Double safeParseDouble(Object s) {
		if (s instanceof Double) {
			Double ig = (Double) s;
			return ig;
		}
		Double i = null;
		try {
			i = new Double((String) s);
		} catch (Exception e) {
		}
		return i;
	}

	public static List<String>[] makeAddCode(Component widget,
			List<String>[] lists, Map<Object, Object> map, String fn) {
		Component wp = WidgetServiceFactory.getService(widget).getParent();
		String parent = (String) map.get(wp);
		if (parent != null) {
			WidgetService pws = WidgetServiceFactory.getService(wp);
			if (pws == null) {
				pws = WidgetServiceFactory.getService(new ContentPanel());
			}
			String addcode = pws.getAddCode(widget, lists, parent, fn, map);
			if (addcode != null) {
				lists[1].add(addcode);
			}
		}
		map.put(widget, fn);
		return lists;
	}

	public static String getFieldName(List<String> l, String fstr, String obstr) {
		Iterator<String> it = l.iterator();
		int i = 0;
		while (it.hasNext()) {
			String s = it.next();
			if (s.startsWith(fstr)) {
				String sf = s.substring(s.lastIndexOf("_") + 1, s.length() - 1);
				i = Integer.parseInt(sf);
			}
		}
		return obstr + "_" + (i + 1);
	}

	public static String makeSetterName(String prop) {
		return "set" + prop.substring(0, 1).toUpperCase() + prop.substring(1);
	}

	public static String makeGetterName(String prop) {
		return "get" + prop.substring(0, 1).toUpperCase() + prop.substring(1);
	}

	public static String makeGetterName(String prop, boolean isBoolean) {
		if (isBoolean) {
			return "is" + prop.substring(0, 1).toUpperCase()
					+ prop.substring(1);

		}
		return "get" + prop.substring(0, 1).toUpperCase() + prop.substring(1);
	}

	public static String getPropName(String methodName) {
		if (methodName.startsWith("is") && methodName.length() > 2) {
			return methodName.substring(2, 3).toLowerCase()
					+ methodName.substring(3);
		}
		if (methodName.length() < 4) {
			return null;
		}
		return methodName.substring(3, 4).toLowerCase()
				+ methodName.substring(4);
	}

	/**
	 * Strimgを特定の文字を区切りとして分割する ()内,"内は区切らない
	 *
	 * @param s
	 * @param c
	 * @return
	 */
	public static List<String> devideStr(String s, int c) {
		List<String> l = new ArrayList<String>();
		int cnt = 0;
		int bg = 0;
		boolean flg = true;
		for (int i = 0; i < s.length(); i++) {
			char ch = s.charAt(i);
			if (ch == '(') {
				cnt++;
			} else if (ch == ')') {
				cnt--;
			} else if (isDC(s, i)) {
				flg = !flg;
			} else if (ch == c && cnt == 0 && flg) {
				l.add(s.substring(bg, i));
				bg = i + 1;
			}
		}
		l.add(s.substring(bg));
		return l;
	}

	private static boolean isDC(String s, int i) {
		char c = s.charAt(i);
		if (c == '"') {
			if (i == 0 || s.charAt(i - 1) != '\\') {
				return true;
			}
		}
		return false;
	}

	public static void setSpacing(CellPanel cp, int spacing) {
		cp.setSpacing(spacing);
		DOM.setElementAttribute(cp.getElement(), "style",
				"border-collapse:separate;border-spacing:" + spacing);
	}

	public static String getNewTag(String tag) {
		Map<String, Integer> map = DesignPanel.getInstance().getWidetCnts();
		Integer cnt = map.get(tag);
		int i;
		if (cnt == null) {
			i = 1;
		} else {
			i = cnt.intValue();
			i++;
		}
		map.put(tag, new Integer(i));
		return tag + i;
	}

	public static native String getSelectorTexts() /*-{
	 var shs = window.parent.document.styleSheets;
	 var res;
	 for (i = 0; i < shs.length; i++) {
	 rls = shs[i].rules;
	 if (rls == null) {
	 rls = shs[i].cssRules;
	 }
	 for (j = 0; j < rls.length; j++) {
	 res = res+"," +rls[j].selectorText;
	 }
	 }
	 return res;
	 }-*/;

	public static String getServerContextURL() {
		// GWT提供のTomcatの場合GWT.getModuleBaseURL()は使用しない
		if (GWT.getModuleBaseURL().indexOf("8888") != -1) {
			return "/";
		} else {
			return GWT.getModuleBaseURL();
		}
	}

	public static boolean isIdEquals(Widget w1, Widget w2) {
		String id1 = DOM.getElementProperty(w1.getElement(), "id");
		String id2 = DOM.getElementProperty(w2.getElement(), "id");
		if (id1 == null) {
			return false;
		}
		return id1.equals(id2);
	}

	public static Component getShallowCopy(Component widget) {
		WidgetService ws = WidgetServiceFactory.getService(widget);
		if (ws == null) {
			return null;
		}
		Component clone = ws.getInstance();
		WidgetService wscl = WidgetServiceFactory.getService(clone);
		if (wscl != null) {
			return wscl.shallowCopy(widget);
		}
		return null;
	}

	public static boolean contains(Object[] os, Object o) {
		if (o == null) {
			return false;
		}
		for (int i = 0; i < os.length; i++) {
			if (o.equals(os[i])) {
				return true;
			}
		}
		return false;
	}

	public static Object doGetter(WidgetService ws, String prop) {
		Object o = ws.exec(GxtUtil.makeGetterName(prop), null);
		if (o == null) {
			o = ws.exec(GxtUtil.makeGetterName(prop, true), null);
		}
		return o;

	}

	public static void resetSize(Component comp) {
		WidgetService ws = WidgetServiceFactory.getService(comp);
		if (comp instanceof BoxComponent) {
			ws.exec("setWidth", new Object[] { ws.exec("getWidth",
					new Object[] { null }) });
			ws.exec("setHeight", new Object[] { ws.exec("getHeight",
					new Object[] { null }) });
		}
		Iterator<Component> it = ws.childrenIterator();
		while (it.hasNext()) {
			resetSize(it.next());
		}
	}

}
