All Downloads are FREE. Search and download functionalities are using the official Maven repository.

xworker.swt.design.Designer Maven / Gradle / Ivy

/*******************************************************************************
* Copyright 2007-2013 See AUTHORS file.
 * 
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* 
*   http://www.apache.org/licenses/LICENSE-2.0
* 
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package xworker.swt.design;

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

import org.eclipse.swt.browser.Browser;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Widget;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xmeta.ActionContext;
import org.xmeta.Thing;
import org.xmeta.World;

import xworker.swt.ActionContainer;

/**
 * SWT设计器。
 * 
 * 如果创建控件的事物的create方法使用了设计器的attach绑定控件,那么改控件可以是设计状态,
 * 当一个控件是设计状态时,使用鼠标中键可以选择控件,并通过鼠标中键的双击打开设计菜单。
 * 
 * @author zyx
 *
 */
public class Designer {
	private static Logger log = LoggerFactory.getLogger(Designer.class);
	public static final String DATA_THING = "_designer_thingPath";
	public static final String DATA_ACTIONCONTEXT = "_designer_actionContext";
	public static final String DATA_ISATTRIBUTE = "_designer_isAttribute";
	public static final String DATA_DESING_SELECTED = "_design_selected";
	public static final String DATA_MARKED = "__design_marked__";
	public static final String DATA_MARKED_PAINTED = "__design_marked__painted";
	public static final String DATA_RESIZE_TYPE = "__design_resize__type__";
	public static final String DATA_RESIZEING = "__design_resizeing__";	
	public static final String TRUE = "true";
	public static final String FALSE = "false";
	
	private static ActionContainer explorerActions = null;
	private static Display explorerDisplay = null; 
	private static boolean enabled = false;
	private static boolean designEditMode = false;
	/** SWT控件Attach时如果大于0,那么先sleep,为测试用 */
	private static long attachSleepTime = 0;
	private static DesignListener listener = new DesignListener();
	private static Map> controlMap = new HashMap>();
	private static List markedControls = new ArrayList();
	/** 标记提示的窗口 */
	private static Shell markTooltipShell = null;
	
	private static final byte BOTTOM = 1;
	private static final byte UP = 2;
	private static final byte RIGHT = 3;
	private static final byte LEFT = 4;
	
	private static Thread markControlThread = new Thread( new Runnable(){
		public void run(){
			while(true){
				try{
					synchronized(markedControls){
						for(int i=0;i ctls = controlMap.get(thingPath);
			if(ctls == null){
				ctls = new ArrayList();
				controlMap.put(thingPath, ctls);
			}
			
			boolean have = false; //避免重复插入,虽然应该不可能
			synchronized(ctls){
				for(int i=0; i < ctls.size(); i++){
					if(ctls.get(i) == control){
						have = true;
						break;
					}
				}
				
				if(!have){
					ctls.add(control);
				}
			}		
			
			if(Designer.attachSleepTime > 0){
				control.getShell().layout();
				if(control.getParent() != null){
					control.getParent().layout();
				}
				Thread.sleep(Designer.attachSleepTime);
			}
		}catch(Throwable t){
			log.error("attach " + thingPath, t);
		}
	}
	
	/**
	 * 标记控件。
	 * 
	 * @param control
	 */
	public static void markControl(final Control control){
		control.getDisplay().asyncExec(new Runnable(){
			public void run(){
				control.setData(Designer.DATA_MARKED, Designer.TRUE);
				redraw(control);	
				
				synchronized(markedControls){
					markedControls.add(control);
				}
			}
		});		
	}	
		
	public static void redraw(final Control control){
		if(control != null && !control.isDisposed()){
			control.getDisplay().asyncExec(new Runnable(){
				public void run(){
					control.redraw();
				}
			});
		}
	}
	
	/**
	 * 取消标记控件。
	 * 
	 * @param control
	 */
	public static void unmarkControl(final Control control){
		control.getDisplay().asyncExec(new Runnable(){
			public void run(){
				control.setData(Designer.DATA_MARKED, null);
				redraw(control);
				
				synchronized(markedControls){
					markedControls.remove(control);
				}
			}
		});	
	}
	
	/**
	 * 解除绑定,在控件销毁时解除。
	 * 
	 * @param control
	 */
	protected static void detach(Widget control){
		String thingPath = (String) control.getData(DATA_THING);
		//ActionContext actionContext = (ActionContext) control.getData("_designer_actionContext");
		
		if(thingPath != null){
			List ctls = controlMap.get(thingPath);
			if(ctls != null){
				synchronized(ctls){
					for(int i=0; i < ctls.size(); i++){
						if(ctls.get(i) == control){
							ctls.remove(i);
							i--;
							//break;
						}
					}
				}
			}
		}
	}
	
	/**
	 * 返回当前编辑器中的指定的控件列表。
	 * 
	 * @param controlPaths
	 * @return
	 */
	public static Map> getControlsInCurrentEditor(List controlPaths){
		Control currentEditor = getActiveEditorRootControl();
		if(currentEditor == null){
			return null;
		}
				
		return getControlsInSameParnet(controlPaths, currentEditor);
	}
	
	/**
	 * 返回编辑器区域内所有编辑器的列表,通常是TabItem或CTabItem。
	 * 
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static List getAllEditorRootControls(){
		if(explorerActions != null){
			return (List) explorerActions.doAction("getActiveEditorRootControl");
		}
		
		return null;
	}
	
	/**
	 * 获取编辑器列表中激活的那个编辑器。
	 * 
	 * @return
	 */
	public static Control getActiveEditorRootControl(){
		if(explorerActions != null){
			return (Control) explorerActions.doAction("getActiveEditorRootControl");
		}
		
		return null;
	}
	
	/**
	 * 获取指定路径的控件列表,并且这些控件都属于指定的父控件。
	 * 
	 * @param controlPaths
	 * @param parent
	 * @return
	 */
	public static Map> getControlsInSameParnet(List controlPaths, Control parent){
		if(controlPaths == null || controlPaths.size() == 0){
			return null;
		}
		
		Map> controls = new HashMap>();
		
		for(String path : controlPaths){
			//根据控件路径查找控件
			List widgets = controlMap.get(path);
			if(widgets != null){			
				for(int i=0; i clist = controls.get(path);
							if(clist == null){
								clist = new ArrayList();
								controls.put(path, clist);
							}
							
							clist.add(control);
						}						
					}
				}
			}
		}
		
		return controls;
	}
	
	private static boolean isSameParent(Control control, Control parent){
		Control theParent = control;		

		while(theParent != null){
			if(theParent == parent){
				return true;
			}
			
			theParent = theParent.getParent();
		}
		
		return false;
	}
	
	/**
	 * 返回创建控件的事物路径。
	 * 
	 * @param control
	 * @return
	 */
	public static String getControlThingPath(Control control){
		return (String) control.getData(Designer.DATA_THING);
	}
	
	/**
	 * 从一个父Control开始寻找对应指定事物的控件,一般该控件是由这个事物创建的。
	 * 
	 * @param control
	 * @param thingPath
	 * @return
	 */
	public static Control findControl(Control control, String thingPath){
		String cpath = getControlThingPath(control);
		if(cpath != null && cpath.equals(thingPath)){
			return control;
		}
		
		if(control instanceof Composite){
			Composite composite = (Composite) control;
			for(Control child : composite.getChildren()){
				Control c = findControl(child, thingPath);
				if(c != null){
					return c;
				}
			}
		}
		
		return null;
	}
	
	/**
	 * 获取属于同一个shell的控件集合,可能或返回多个集合,值返回全部空间都同时存在的集合。
	 * 
	 * @param controlPaths
	 * @return 
	 */
	public static List>> getControlsInSameShell(List controlPaths){
		if(controlPaths == null || controlPaths.size() == 0){
			return null;
		}
		
		List>> controlList = new ArrayList>>();
		String firstPath = controlPaths.get(0);
		
		for(String path : controlPaths){
			//根据控件路径查找控件
			List widgets = controlMap.get(path);
			if(widgets != null){			
				for(int i=0; i> controlMap : controlList){
							List controls  = controlMap.get(firstPath);
							if(controls.get(0).getShell() == shell){
								addControl(path, controlMap, control);
								have = true;
								break;
							}
						}
						
						if(!have){
							if(path.equals(firstPath)){
								//如果是第一个控件,那么创建一个map,否则不添加到列表中
								Map> controlMap = new HashMap>();
								List controls = new ArrayList();
								controls.add(control);
								controlMap.put(path, controls);
								controlList.add(controlMap);
							}
						}
					}
				}
			}
		}
		
		//移除控件不全的,必须返回所有路径都有对应控件的
		for(int i=0; i> controlMap = controlList.get(i);
			
			boolean have = true;
			for(String path : controlPaths){
				if(controlMap.get(path) == null){
					have = false;
					break;
				}
			}
			
			if(!have){
				controlList.remove(i);
				i--;
			}
		}
		
		return controlList;
	}
	
	private static void addControl(String path, Map> controlMap, Control control){
		List controlList = controlMap.get(path);
		if(controlList == null){
			controlList = new ArrayList();
			controlMap.put(path, controlList);
		}
		
		controlList.add(control);
	}
	
	public static Control getActiveControl(String path){
		List widgets = controlMap.get(path);
		if(widgets != null){			
			for(int i=0; i




© 2015 - 2025 Weber Informatics LLC | Privacy Policy