模型部分:
标尺提供者:
向导操作命令:
最后在编辑器中配置RulerComposite(因为GEF是支持RulerComposite的,所以配置就可以了)
最后在configureGraphicalViewer方法中调用configureRuler即可
public class ElementBase extends AbstractModel implements IAdaptable {
/**
*
*/
private static final long serialVersionUID = 1L;
/**
* 布局
*/
private Rectangle layout;
/**
* 获得布局
*
* @return
*/
public Rectangle getLayout() {
return layout;
}
public void setLayout(Rectangle layout) {
this.layout = layout;
}
/**
* 垂直向导、水平向导
*/
private Guide verticalGuide, horizontalGuide;
public Guide getVerticalGuide() {
return verticalGuide;
}
/**
* 设置导航参数
*
* @param verticalGuide
*/
public void setVerticalGuide(Guide verticalGuide) {
this.verticalGuide = verticalGuide;
}
public Guide getHorizontalGuide() {
return horizontalGuide;
}
public void setHorizontalGuide(Guide horizontalGuide) {
this.horizontalGuide = horizontalGuide;
}
public Object getAdapter(Class adapter) {
return null;
}
/**
* 向导
*
* @author Ming.He
*
*/
public class Guide implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
/**
* 对于一个向导, 当附件部分被改变时,这个属性通常用来通知监听者
*/
public static final String PROPERTY_CHILDREN = "subparts changed";
/**
*
* Property used to notify listeners when the guide is re-positioned
*/
public static final String PROPERTY_POSITION = "position changed";
protected PropertyChangeSupport listeners = new PropertyChangeSupport(this);
private Map map;
/**
* 定位
*/
private int position;
/**
* 是否水平
*/
private boolean horizontal;
/**
*
* Empty default constructor
*/
public Guide() {
// empty constructor
}
/**
*
* Constructor
*
*
*
* @param isHorizontal
*
* <code>true</code> if the guide is horizontal (i.e., placed on
*
* a vertical ruler)
*/
public Guide(boolean isHorizontal) {
setHorizontal(isHorizontal);
}
/**
*
* @see PropertyChangeSupport#addPropertyChangeListener(java.beans.PropertyChangeListener)
*/
public void addPropertyChangeListener(PropertyChangeListener listener) {
listeners.addPropertyChangeListener(listener);
}
/*
*
* @TODO:Pratik use PositionConstants here
*/
/**
*
* Attaches the given part along the given edge to this guide. The
*
* LogicSubpart is also updated to reflect this attachment.
*
*
*
* @param part
*
* The part that is to be attached to this guide; if the part is
*
* already attached, its alignment is updated
*
* @param alignment
*
* -1 is left or top; 0, center; 1, right or bottom
*/
public void attachElement(ElementBase element, int alignment) {
if (getMap().containsKey(element) && getAlignment(element) == alignment)
return;
getMap().put(element, alignment);
Guide parent = isHorizontal() ? element.getHorizontalGuide() : element
.getVerticalGuide();
if (parent != null && parent != this) {
parent.detachElement(element);
}
if (isHorizontal()) {
element.setHorizontalGuide(this);
} else {
element.setVerticalGuide(this);
}
listeners.firePropertyChange(PROPERTY_CHILDREN, null, element);
}
/**
*
* Detaches the given part from this guide. The LogicSubpart is also updated
*
* to reflect this change.
*
*
*
* @param part
*
* the part that is to be detached from this guide
*/
public void detachElement(ElementBase element) {
if (getMap().containsKey(element)) {
getMap().remove(element);
if (isHorizontal()) {
element.setHorizontalGuide(null);
} else {
element.setVerticalGuide(null);
}
listeners.firePropertyChange(PROPERTY_CHILDREN, null, element);
}
}
/**
*
* This methods returns the edge along which the given part is attached to
*
* this guide. This information is used by
*
* {@link org.eclipse.gef.examples.logicdesigner.edit.LogicXYLayoutEditPolicy
*
* LogicXYLayoutEditPolicy} to determine whether to attach or detach a part
*
* from a guide during resize operations.
*
*
*
* @param part
*
* The part whose alignment has to be found
*
* @return an int representing the edge along which the given part is
*
* attached to this guide; 1 is bottom or right; 0, center; -1, top
*
* or left; -2 if the part is not attached to this guide
*
* @see org.eclipse.gef.examples.logicdesigner.edit.LogicXYLayoutEditPolicy#createChangeConstraintCommand(ChangeBoundsRequest,
* EditPart, Object)
*/
public int getAlignment(ElementBase element) {
if (getMap().get(element) != null)
return ((Integer) getMap().get(element)).intValue();
return -2;
}
/**
*
* @return The Map containing all the parts attached to this guide, and
*
* their alignments; the keys are LogicSubparts and values are
*
* Integers
*/
public Map getMap() {
if (map == null) {
map = new Hashtable();
}
return map;
}
/**
*
* @return the set of all the parts attached to this guide; a set is used
*
* because a part can only be attached to a guide along one edge.
*/
public Set getParts() {
return getMap().keySet();
}
/**
*
* @return the position/location of the guide (in pixels)
*/
public int getPosition() {
return position;
}
/**
*
* @return <code>true</code> if the guide is horizontal (i.e., placed on a
*
* vertical ruler)
*/
public boolean isHorizontal() {
return horizontal;
}
/**
*
* @see PropertyChangeSupport#removePropertyChangeListener(java.beans.PropertyChangeListener)
*/
public void removePropertyChangeListener(PropertyChangeListener listener) {
listeners.removePropertyChangeListener(listener);
}
/**
*
* Sets the orientation of the guide
*
*
*
* @param isHorizontal
*
* <code>true</code> if this guide is to be placed on a vertical
*
* ruler
*/
public void setHorizontal(boolean isHorizontal) {
horizontal = isHorizontal;
}
/**
*
* Sets the location of the guide
*
*
*
* @param offset
*
* The location of the guide (in pixels)
*/
public void setPosition(int offset) {
if (position != offset) {
int oldValue = position;
position = offset;
listeners.firePropertyChange(PROPERTY_POSITION, new Integer(
oldValue), new Integer(position));
}
}
}
/**
* 标尺
*
* @author Ming.He
*
*/
public class Ruler implements Serializable {
public static final String PROPERTY_CHILDREN = "children changed";
public static final String PROPERTY_UNIT = "units changed";
static final long serialVersionUID = 1;
protected PropertyChangeSupport listeners = new PropertyChangeSupport(this);
private int unit;
private boolean horizontal;
private List<Guide> guides = new ArrayList<Guide>();
public Ruler(boolean isHorizontal) {
this(isHorizontal, RulerProvider.UNIT_PIXELS);
}
public Ruler(boolean isHorizontal, int unit) {
horizontal = isHorizontal;
setUnit(unit);
}
public void addGuide(Guide guide) {
if (!guides.contains(guide)) {
guide.setHorizontal(!isHorizontal());
guides.add(guide);
listeners.firePropertyChange(PROPERTY_CHILDREN, null, guide);
}
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
listeners.addPropertyChangeListener(listener);
}
// the returned list should not be modified
public List<Guide> getGuides() {
return guides;
}
public int getUnit() {
return unit;
}
public boolean isHidden() {
return false;
}
public boolean isHorizontal() {
return horizontal;
}
public void removeGuide(Guide guide) {
if (guides.remove(guide)) {
listeners.firePropertyChange(PROPERTY_CHILDREN, null, guide);
}
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
listeners.removePropertyChangeListener(listener);
}
public void setHidden(boolean isHidden) {
}
public void setUnit(int newUnit) {
if (unit != newUnit) {
int oldUnit = unit;
unit = newUnit;
listeners.firePropertyChange(PROPERTY_UNIT, oldUnit, newUnit);
}
}
}
标尺提供者:
/**
* 编辑器标尺提供者
*
* @author Ming.He
*
*/
public class EditorRulerProvider extends RulerProvider {
/** 标尺 */
private Ruler ruler;
/** 标尺监听 */
private PropertyChangeListener rulerListener = new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName().equals(Ruler.PROPERTY_CHILDREN)) {
Guide guide = (Guide) evt.getNewValue();
if (getGuides().contains(guide)) {
guide.addPropertyChangeListener(guideListener);
} else {
guide.removePropertyChangeListener(guideListener);
}
for (int i = 0; i < listeners.size(); i++) {
((RulerChangeListener) listeners.get(i))
.notifyGuideReparented(guide);
}
} else {
for (int i = 0; i < listeners.size(); i++) {
((RulerChangeListener) listeners.get(i))
.notifyUnitsChanged(ruler.getUnit());
}
}
}
};
private PropertyChangeListener guideListener = new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName().equals(Guide.PROPERTY_CHILDREN)) {
for (int i = 0; i < listeners.size(); i++) {
((RulerChangeListener) listeners.get(i))
.notifyPartAttachmentChanged(evt.getNewValue(), evt
.getSource());
}
} else {
for (int i = 0; i < listeners.size(); i++) {
((RulerChangeListener) listeners.get(i))
.notifyGuideMoved(evt.getSource());
}
}
}
};
public EditorRulerProvider(Ruler ruler) {
this.ruler = ruler;
this.ruler.addPropertyChangeListener(rulerListener);
List guides = getGuides();
for (int i = 0; i < guides.size(); i++) {
((Guide) guides.get(i))
.addPropertyChangeListener(guideListener);
}
}
public List getAttachedModelObjects(Object guide) {
return new ArrayList(((Guide) guide).getParts());
}
public Command getCreateGuideCommand(int position) {
return new CreateGuideCommand(ruler, position);
}
public Command getDeleteGuideCommand(Object guide) {
return new DeleteGuideCommand((Guide) guide, ruler);
}
public Command getMoveGuideCommand(Object guide, int pDelta) {
return new MoveGuideCommand((Guide) guide, pDelta);
}
public int[] getGuidePositions() {
List guides = getGuides();
int[] result = new int[guides.size()];
for (int i = 0; i < guides.size(); i++) {
result[i] = ((Guide) guides.get(i)).getPosition();
}
return result;
}
public Object getRuler() {
return ruler;
}
public int getUnit() {
return ruler.getUnit();
}
public void setUnit(int newUnit) {
ruler.setUnit(newUnit);
}
public int getGuidePosition(Object guide) {
return ((Guide) guide).getPosition();
}
public List getGuides() {
return ruler.getGuides();
}
}
向导操作命令:
/**
* 创建向导命令
*
* @author Ming.He
*
*/
public class CreateGuideCommand extends Command {
/** 向导 */
private Guide guide;
/** 标尺 */
private Ruler parent;
/** 位置 */
private int position;
public CreateGuideCommand(Ruler parent, int position) {
super("Create guide");
this.parent = parent;
this.position = position;
}
public boolean canUndo() {
return true;
}
public void execute() {
if (guide == null)
guide = new Guide(!parent.isHorizontal());
guide.setPosition(position);
parent.addGuide(guide);
}
public void undo() {
parent.removeGuide(guide);
}
}
/**
* 删除向导命令
* @author Ming.He
*
*/
public class DeleteGuideCommand extends Command {
/**
* 标尺
*/
private Ruler parent;
/**
* 向导
*/
private Guide guide;
/**
* 已创建的控制器
*/
private Map oldParts;
public DeleteGuideCommand(Guide guide, Ruler parent) {
super("Delete guide");
this.guide = guide;
this.parent = parent;
}
public boolean canUndo() {
return true;
}
public void execute() {
oldParts = new HashMap(guide.getMap());
Iterator iter = oldParts.keySet().iterator();
while (iter.hasNext()) {
guide.detachElement((ElementBase) iter.next());
}
parent.removeGuide(guide);
}
public void undo() {
parent.addGuide(guide);
Iterator iter = oldParts.keySet().iterator();
while (iter.hasNext()) {
ElementBase element = (ElementBase) iter.next();
guide.attachElement(element, ((Integer) oldParts.get(element)).intValue());
}
}
}
/**
* 移动向导命令
* @author Ming.He
*
*/
public class MoveGuideCommand extends Command {
/**三角定位*/
private int pDelta;
/**向导*/
private Guide guide;
public MoveGuideCommand(Guide guide, int positionDelta) {
super("Move guide");
this.guide = guide;
pDelta = positionDelta;
}
public void execute() {
guide.setPosition(guide.getPosition() + pDelta);
Iterator iter = guide.getParts().iterator();
while (iter.hasNext()) {
ElementBase element = (ElementBase) iter.next();
Rectangle layout = element.getLayout().getCopy();
if (guide.isHorizontal()) {
layout.y += pDelta;
} else {
layout.x += pDelta;
}
element.setLayout(layout);
}
}
public void undo() {
guide.setPosition(guide.getPosition() - pDelta);
Iterator iter = guide.getParts().iterator();
while (iter.hasNext()) {
ElementBase element = (ElementBase) iter.next();
Rectangle layout = element.getLayout().getCopy();
if (guide.isHorizontal()) {
layout.y -= pDelta;
} else {
layout.x -= pDelta;
}
element.setLayout(layout);
}
}
}
最后在编辑器中配置RulerComposite(因为GEF是支持RulerComposite的,所以配置就可以了)
/** 标尺容器 */
private RulerComposite rulerComp;// Override
protected void createGraphicalViewer(Composite parent) {
rulerComp = new RulerComposite(parent, SWT.NONE);
super.createGraphicalViewer(rulerComp);
rulerComp.setGraphicalViewer((ScrollingGraphicalViewer) getGraphicalViewer());
}
/**
* 配置标尺
*/
private void configureRuler() {
GraphicalViewer viewer = getGraphicalViewer();
viewer.setProperty(RulerProvider.PROPERTY_VERTICAL_RULER,
new EditorRulerProvider(new Ruler(false)));
viewer.setProperty(RulerProvider.PROPERTY_HORIZONTAL_RULER,
new EditorRulerProvider(new Ruler(true)));
viewer.setProperty(RulerProvider.PROPERTY_RULER_VISIBILITY, true);
IAction action = new ToggleRulerVisibilityAction(getGraphicalViewer());
getActionRegistry().registerAction(action);
}
最后在configureGraphicalViewer方法中调用configureRuler即可