LayoutManager布局管理

不要设置figure的大小,而是应该在父中用setConstraint方法设置子的大小,

就像在swt里我们使用layout来控制各个控件的摆放位置一样,在Draw2D里最好也把这个工作交给LayoutManager来做。除非是在自己实现的Layout里,一般程序里自己不要轻易使用setBounds()、setLocation()和setSize()这些方法控制图形的位置和大小,而应该在为每个图形设置了适当的LayoutManager后,通过setConstraint()和setPreferredSize()等方法告诉layoutmanager如何布局。

 

 

在之前没有理解LayoutManager,如是就以一种尊重原著的心态,在实现一个复杂的编辑器布局的时候,拼命的用draw2d默认提供的布局进行拼凑,最终结果是代码的复杂度和耦合度急剧上升。

其实如果换一种思路,就是一个容器里面除了要显示的子,不应该为了布局而额外出现一些IFigure,就算出现也应该是尽量少的出现。当默认的布局不够用的时候,应该尝试自己扩展一个有效的LayoutManager。

 

这里顺便提一下SWT的局限性:SWT里面容器组件的布局跟容器组件是绑定的,也就是说,如果一个组件里面需要多种布局。它就必须有多个子,然后每个子里面再选择布局。如果从设计上布局就是一个没有形状只有规则的子,这样就显得更合理。

 

LayoutManager接口:布局管理器的基础接口,其中layout方法最为重要,在此次处实现布局的规则。另外invalidate起到一个清空的作用。

 

AbstractLayout:抽象实现。里面增加了两个属性:preferredSize容器的首选大小,isObservingVisibility我的理解这个属性描述的是,是否完全可见。这个类提供了一个抽象方法供其子实现,calculatePreferredSize(IFigure container,int wHint, int hHint)计算容器的大小,另外在setConstraint里面对子元素的位置信息进行清空,位置变了需要重新计算。

setConstraint(IFigure figure, Object constraint):方法中第二个参数是根据布局的需要来传入的,不一定是Rectangle

 

对于一个真实有效的布局管理器来说,它必须做两件事情:

1.一个就是根据一定的规则,算出整个容器的大小。如果大小不可以改变,那么就不能改变。

2.在Layout方法里面定义出一套规则来摆放它的子节点。

 

XYLayout:自由布局,绝对定位的布局。XY中有一个Map constraints保存了子的尺寸。如下是XYLayout实现布局的代码:

 

 

public void layout(IFigure parent) {
		Iterator children = parent.getChildren().iterator();
		Point offset = getOrigin(parent);
		IFigure f;
		while (children.hasNext()) {
			f = (IFigure) children.next();
			Rectangle bounds = (Rectangle) getConstraint(f);
			if (bounds == null)
				continue;

			if (bounds.width == -1 || bounds.height == -1) {
				Dimension preferredSize = f.getPreferredSize(bounds.width,
						bounds.height);
				bounds = bounds.getCopy();
				if (bounds.width == -1)
					bounds.width = preferredSize.width;
				if (bounds.height == -1)
					bounds.height = preferredSize.height;
			}
			bounds = bounds.getTranslated(offset);
			f.setBounds(bounds);
		}
	}
 

 

第一步它获取父的x,y坐标offset,然后计算每个子的矩形区域Rectangle,其中对超出边界的矩形做了一些处理。里面

句话没看明白:bounds = bounds.getCopy();没看懂。getConstraint中放的都是设置的Rectangle,而

getPreferredSize里面放的是首选矩形。

 

注意:这里的绝对定位是相对父容器来说的,而不是整个界面来说。

 

RulerLayout:继承自XYLayout,它是gef主要用来实现ZoomManager功能的时候自己扩展的,在gef中还有RulerFigure,RulerEditPart之类的,这个布局管理器并不通用。

 

public void layout(IFigure container) {
		List children = container.getChildren();
		Rectangle rulerSize = container.getClientArea();
		for (int i = 0; i < children.size(); i++) {
			IFigure child = (IFigure) children.get(i);
			Dimension childSize = child.getPreferredSize();
			int position = ((Integer) getConstraint(child)).intValue();
			if (((RulerFigure) container).isHorizontal()) {
				childSize.height = rulerSize.height - 1;
				Rectangle.SINGLETON.setLocation(position
						- (childSize.width / 2), rulerSize.y);
			} else {
				childSize.width = rulerSize.width - 1;
				Rectangle.SINGLETON.setLocation(rulerSize.x, position
						- (childSize.height / 2));
			}
			Rectangle.SINGLETON.setSize(childSize);
			child.setBounds(Rectangle.SINGLETON);
		}
	}
 

FreeformLayout:继承自XYLayout,它的布局方式跟XYLayout一样,只是重写了getOrigin(IFigure figure)方法,在获取Origin坐标的时候有所不同。

 

 

AbstractHintLayout:继承自AbstractLayout,它提供了一个calculateMinimumSize方法用于计算长度和宽度。AbstractHintLayout的子类都是尺寸敏感位置不敏感的相对布局。

 

 

还有好几种相对布局,暂时先不总结

BorderLayout:一个东南西北中的布局,里面有五个静态常量来描述位置。

 

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(manager)