在前面的博文中,已经提及,在为我们的EditPart安装LayoutEditPolicy策略时,LayoutEditPolicy会为它的所有孩子安装策略(decorateChildren),实际上是安装了PRIMARY_DRAG_ROLE策略,一般情况会是SelectionEditPolicy的子类。
我们先来看看SelectionEditPolicy的activate方法的源代码:
public void activate() {
super.activate();
addSelectionListener();
setSelectedState(getHost().getSelected());
setFocus(getHost().hasFocus());
}
我们注意到了addSelectionListener方法,好像是添加了选中监听器。
跟踪进去看看,
protected void addSelectionListener() {
selectionListener = new EditPartListener.Stub() {
public void selectedStateChanged(EditPart part) {
setSelectedState(part.getSelected());//更新选中状态
setFocus(part.hasFocus());
}
};
getHost().addEditPartListener(selectionListener);//给EditPolicy的Host添加了EditPartListener监听器
}
接着看看setSelectedState方法代码。
protected void setSelectedState(int type) {
if (state == type)
return;
state = type;
if (type == EditPart.SELECTED_PRIMARY)
showPrimarySelection();
else if (type == EditPart.SELECTED)
showSelection();
else
hideSelection();
}
showPrimarySelection内部就是调用了showSelection。
接着看showSelection的实现。showSelection是个抽象方法,先看看SelectionEditPolicy的子类SelectionHandlesEditPolicy是怎样实现的
protected void showSelection() {
addSelectionHandles();
}
关键方法是addSelectionHandles:
protected void addSelectionHandles() {
removeSelectionHandles();
IFigure layer = getLayer(LayerConstants.HANDLE_LAYER);//获取Handle层
handles = createSelectionHandles();//抽象方法
for (int i = 0; i < handles.size(); i++)
layer.add((IFigure)handles.get(i));//将handle加到Handle Layer中
}
createSelectionHandles是一个抽象方法,我们看看SelectionHandlesEditPolicy子类ResizableEditPolicy中是如何实现createSelectionHandles的。
//创建了8个Handle
/**
* @see org.eclipse.gef.editpolicies.SelectionHandlesEditPolicy#createSelectionHandles()
* 创建选中EditPart时的Handle
*/
protected List createSelectionHandles() {
List list = new ArrayList();
if (directions == 0)
NonResizableHandleKit.addHandles((GraphicalEditPart)getHost(), list);
else if (directions != -1) {
ResizableHandleKit.addMoveHandle((GraphicalEditPart)getHost(), list);
if ((directions & PositionConstants.EAST) != 0)
ResizableHandleKit.addHandle((GraphicalEditPart)getHost(), list,
PositionConstants.EAST);
else
NonResizableHandleKit.addHandle((GraphicalEditPart)getHost(), list,
PositionConstants.EAST);
if ((directions & PositionConstants.SOUTH_EAST) == PositionConstants.SOUTH_EAST)
ResizableHandleKit.addHandle((GraphicalEditPart)getHost(), list,
PositionConstants.SOUTH_EAST);
else
NonResizableHandleKit.addHandle((GraphicalEditPart)getHost(), list,
PositionConstants.SOUTH_EAST);
if ((directions & PositionConstants.SOUTH) != 0)
ResizableHandleKit.addHandle((GraphicalEditPart)getHost(), list,
PositionConstants.SOUTH);
else
NonResizableHandleKit.addHandle((GraphicalEditPart)getHost(), list,
PositionConstants.SOUTH);
if ((directions & PositionConstants.SOUTH_WEST) == PositionConstants.SOUTH_WEST)
ResizableHandleKit.addHandle((GraphicalEditPart)getHost(), list,
PositionConstants.SOUTH_WEST);
else
NonResizableHandleKit.addHandle((GraphicalEditPart)getHost(), list,
PositionConstants.SOUTH_WEST);
if ((directions & PositionConstants.WEST) != 0)
ResizableHandleKit.addHandle((GraphicalEditPart)getHost(), list,
PositionConstants.WEST);
else
NonResizableHandleKit.addHandle((GraphicalEditPart)getHost(), list,
PositionConstants.WEST);
if ((directions & PositionConstants.NORTH_WEST) == PositionConstants.NORTH_WEST)
ResizableHandleKit.addHandle((GraphicalEditPart)getHost(), list,
PositionConstants.NORTH_WEST);
else
NonResizableHandleKit.addHandle((GraphicalEditPart)getHost(), list,
PositionConstants.NORTH_WEST);
if ((directions & PositionConstants.NORTH) != 0)
ResizableHandleKit.addHandle((GraphicalEditPart)getHost(), list,
PositionConstants.NORTH);
else
NonResizableHandleKit.addHandle((GraphicalEditPart)getHost(), list,
PositionConstants.NORTH);
if ((directions & PositionConstants.NORTH_EAST) == PositionConstants.NORTH_EAST)
ResizableHandleKit.addHandle((GraphicalEditPart)getHost(), list,
PositionConstants.NORTH_EAST);
else
NonResizableHandleKit.addHandle((GraphicalEditPart)getHost(), list,
PositionConstants.NORTH_EAST);
} else
ResizableHandleKit.addHandles((GraphicalEditPart)getHost(), list);
return list;
}
现在我们应该已经弄清楚了,我们选中某个EditPart时,显示8个Handle点的流程了,因为EditPart添加了SelectionListener,当选中状态发生改变时,都会显示8个Handle点(如果你安装的是ResizableEditPolicy)。
问题的关键是,EditPart的选中状态是怎么改变的呢?
我们接下来看看这个问题。
看看AbstractEditPart中的setSelected方法的内容。
public void setSelected(int value) {
if (selected == value)
return;
selected = value;
fireSelectionChanged();//选择EditPart并触发选择事件
}
fireSelectionChanged的代码如下:
/**
* Notifies <code>EditPartListeners</code> that the
* selection has changed.
*/
protected void fireSelectionChanged() {
Iterator listeners = getEventListeners(EditPartListener.class);
while (listeners.hasNext())
((EditPartListener)listeners.next()).
selectedStateChanged(this);
}