Sponsored link
BorderLayoutのCenterの伸びをカスタム(Draw2D/GEF - Java Eclipse)
単純に、LabelFigureを5箇所に追加してみました。

左が普通のBorderLayout
真ん中は、カスタムで元のFigureのサイズのまま
右は、カスタムでFigureのサイズを幅・高さ共に拡張したものです。
Draw2DのBorderLayoutは、なぜかCenterのWidthのみ、サイズは拡張されます。
両方するか、しないかの方が、わかりやすいと思いますが。
ラベルが挿入されることを意識したのだと思います。
しかし、CenterのFigureサイズをどうするか制御出来た方が便利だと思い
他の方法が見つからなかったので、わたしはこの方法を使っています。
あといくつか、動作のサンプル画像を載せておきます。

コード解説
StretchCenterHeightとStretchCenterWidth
ネーミングのセンスはさておき、以下のように、
stretchCenterWidthとstretchCenterHeightのboolean変数を作成しました。
一応、デフォルトで普通のBorderLayoutと同じ動きをするようにしてます。
private boolean stretchCenterWidth=true;
private boolean stretchCenterHeight=false;
public boolean isStretchCenterHeight() {
return stretchCenterHeight;
}
public void setStretchCenterHeight(boolean stretchCenterHeight) {
this.stretchCenterHeight = stretchCenterHeight;
}
public boolean isStretchCenterWidth() {
return stretchCenterWidth;
}
public void setStretchCenterWidth(boolean stretchCenterWidth) {
this.stretchCenterWidth = stretchCenterWidth;
}
layout()
layoutでは元々、childFigureのHeightが、小さければ拡張するようになってました。
これを、制御できるようにと、Widthには適用してみました。
childSize = center.getPreferredSize(
Math.max(0, area.width),
Math.max(0, area.height));
if(!stretchCenterHeight){
if (childSize.height < area.height) {
area.y += (area.height - childSize.height) / 2;
area.height = childSize.height;
}
}
if(!stretchCenterWidth){
if (childSize.width < area.width) {
area.x += (area.width - childSize.width) / 2;
area.width = childSize.width;
}
}
呼び出し
あとは、BorderLayoutの変わりに、CustomLayoutを作成して、
拡張するかどうかを指定します。
CustomBorderLayout layout=new CustomBorderLayout(); layout.setStretchCenterWidth(true); layout.setStretchCenterHeight(true);
コードフル
コードはCVSからダウンロードできます。
CustomBorderLayoutTest
以前、BorderLayoutの解説で使ったコードとほとんど同じです。
/*
* Created on 2005/08/02
* Author aki@www.xucker.jpn.org
* License Apache2.0 or Common Public License
*/
package example.draw2d;
import org.eclipse.draw2d.BorderLayout;
import org.eclipse.draw2d.ColorConstants;
import org.eclipse.draw2d.Figure;
import org.eclipse.draw2d.FigureCanvas;
import org.eclipse.draw2d.Label;
import org.eclipse.draw2d.LineBorder;
import org.eclipse.draw2d.Panel;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
/**
*
*
*/
public class CustomBorderLayoutTest {
public CustomBorderLayoutTest(Shell shell) {
shell.setBounds(0,0,150,150);
shell.setLayout(new FillLayout(SWT.VERTICAL));
FigureCanvas canvas = new FigureCanvas(shell);
Panel panel=new Panel();
panel.setBackgroundColor(ColorConstants.orange);
canvas.setContents(panel);
//BorderLayout layout=new BorderLayout();
CustomBorderLayout layout=new CustomBorderLayout();
layout.setStretchCenterWidth(true);
layout.setStretchCenterHeight(true);
//layout.setHorizontalSpacing(5);
//layout.setVerticalSpacing(5);
panel.setLayoutManager(layout);
set(panel,"top",BorderLayout.TOP);
set(panel,"bottom",BorderLayout.BOTTOM);
set(panel,"center",BorderLayout.CENTER);
set(panel,"left",BorderLayout.LEFT);
set(panel,"right",BorderLayout.RIGHT);
}
public void set(Figure parent,String label,Object constants){
Label labelFigure=new Label(label);
labelFigure.setBorder(new LineBorder());
parent.add(labelFigure,constants);
}
public static void main(String[] args) {
Display display=new Display();
Shell shell=new Shell(display);
CustomBorderLayoutTest app=new CustomBorderLayoutTest(shell);
shell.open();
while(!shell.isDisposed()){
if (!display.readAndDispatch ()){
display.sleep ();
}
}
display.dispose();
}
}
CustomBorderLayout
ほとんど、BorderLayoutと同じです。
package example.draw2d;
import org.eclipse.draw2d.AbstractLayout;
import org.eclipse.draw2d.BorderLayout;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.PositionConstants;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Insets;
import org.eclipse.draw2d.geometry.Rectangle;
/*******************************************************************************
* Copyright (c) 2000, 2005 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
public class CustomBorderLayout extends BorderLayout{
/**
* Constant to be used as a constraint for child figures
*/
public static final Integer CENTER = new Integer(PositionConstants.CENTER);
/**
* Constant to be used as a constraint for child figures
*/
public static final Integer TOP = new Integer(PositionConstants.TOP);
/**
* Constant to be used as a constraint for child figures
*/
public static final Integer BOTTOM = new Integer(PositionConstants.BOTTOM);
/**
* Constant to be used as a constraint for child figures
*/
public static final Integer LEFT = new Integer(PositionConstants.LEFT);
/**
* Constant to be used as a constraint for child figures
*/
public static final Integer RIGHT = new Integer(PositionConstants.RIGHT);
private IFigure center, left, top, bottom, right;
private int vGap = 0, hGap = 0;
private boolean stretchCenterWidth=true;
private boolean stretchCenterHeight=false;
/**
* @see org.eclipse.draw2d.AbstractHintLayout#calculateMinimumSize(IFigure, int, int)
*/
protected Dimension calculateMinimumSize(IFigure container, int wHint, int hHint) {
int minWHint = 0, minHHint = 0;
if (wHint < 0) {
minWHint = -1;
}
if (hHint < 0) {
minHHint = -1;
}
Insets border = container.getInsets();
wHint = Math.max(minWHint, wHint - border.getWidth());
hHint = Math.max(minHHint, hHint - border.getHeight());
Dimension minSize = new Dimension();
int middleRowWidth = 0, middleRowHeight = 0;
int rows = 0, columns = 0;
if (top != null && top.isVisible()) {
Dimension childSize = top.getMinimumSize(wHint, hHint);
hHint = Math.max(minHHint, hHint - (childSize.height + vGap));
minSize.setSize(childSize);
rows += 1;
}
if (bottom != null && bottom.isVisible()) {
Dimension childSize = bottom.getMinimumSize(wHint, hHint);
hHint = Math.max(minHHint, hHint - (childSize.height + vGap));
minSize.width = Math.max(minSize.width, childSize.width);
minSize.height += childSize.height;
rows += 1;
}
if (left != null && left.isVisible()) {
Dimension childSize = left.getMinimumSize(wHint, hHint);
middleRowWidth = childSize.width;
middleRowHeight = childSize.height;
wHint = Math.max(minWHint, wHint - (childSize.width + hGap));
columns += 1;
}
if (right != null && right.isVisible()) {
Dimension childSize = right.getMinimumSize(wHint, hHint);
middleRowWidth += childSize.width;
middleRowHeight = Math.max(childSize.height, middleRowHeight);
wHint = Math.max(minWHint, wHint - (childSize.width + hGap));
columns += 1;
}
if (center != null && center.isVisible()) {
Dimension childSize = center.getMinimumSize(wHint, hHint);
middleRowWidth += childSize.width;
middleRowHeight = Math.max(childSize.height, middleRowHeight);
columns += 1;
}
rows += columns > 0 ? 1 : 0;
// Add spacing, insets, and the size of the middle row
minSize.height += middleRowHeight + border.getHeight() + ((rows - 1) * vGap);
minSize.width = Math.max(minSize.width, middleRowWidth) + border.getWidth()
+ ((columns - 1) * hGap);
return minSize;
}
/**
* @see AbstractLayout#calculatePreferredSize(IFigure, int, int)
*/
protected Dimension calculatePreferredSize(IFigure container, int wHint, int hHint) {
int minWHint = 0, minHHint = 0;
if (wHint < 0)
minWHint = -1;
if (hHint < 0)
minHHint = -1;
Insets border = container.getInsets();
wHint = Math.max(minWHint, wHint - border.getWidth());
hHint = Math.max(minHHint, hHint - border.getHeight());
Dimension prefSize = new Dimension();
int middleRowWidth = 0, middleRowHeight = 0;
int rows = 0, columns = 0;
if (top != null && top.isVisible()) {
Dimension childSize = top.getPreferredSize(wHint, hHint);
hHint = Math.max(minHHint, hHint - (childSize.height + vGap));
prefSize.setSize(childSize);
rows += 1;
}
if (bottom != null && bottom.isVisible()) {
Dimension childSize = bottom.getPreferredSize(wHint, hHint);
hHint = Math.max(minHHint, hHint - (childSize.height + vGap));
prefSize.width = Math.max(prefSize.width, childSize.width);
prefSize.height += childSize.height;
rows += 1;
}
if (left != null && left.isVisible()) {
Dimension childSize = left.getPreferredSize(wHint, hHint);
middleRowWidth = childSize.width;
middleRowHeight = childSize.height;
wHint = Math.max(minWHint, wHint - (childSize.width + hGap));
columns += 1;
}
if (right != null && right.isVisible()) {
Dimension childSize = right.getPreferredSize(wHint, hHint);
middleRowWidth += childSize.width;
middleRowHeight = Math.max(childSize.height, middleRowHeight);
wHint = Math.max(minWHint, wHint - (childSize.width + hGap));
columns += 1;
}
if (center != null && center.isVisible()) {
Dimension childSize = center.getPreferredSize(wHint, hHint);
middleRowWidth += childSize.width;
middleRowHeight = Math.max(childSize.height, middleRowHeight);
columns += 1;
}
rows += columns > 0 ? 1 : 0;
// Add spacing, insets, and the size of the middle row
prefSize.height += middleRowHeight + border.getHeight() + ((rows - 1) * vGap);
prefSize.width = Math.max(prefSize.width, middleRowWidth) + border.getWidth()
+ ((columns - 1) * hGap);
return prefSize;
}
/**
* @see org.eclipse.draw2d.LayoutManager#layout(IFigure)
*/
public void layout(IFigure container) {
Rectangle area = container.getClientArea();
Rectangle rect = new Rectangle();
Dimension childSize;
if (top != null && top.isVisible()) {
childSize = top.getPreferredSize(area.width, -1);
rect.setLocation(area.x, area.y);
rect.setSize(childSize);
rect.width = area.width;
top.setBounds(rect);
area.y += rect.height + vGap;
area.height -= rect.height + vGap;
}
if (bottom != null && bottom.isVisible()) {
childSize = bottom.getPreferredSize(Math.max(area.width, 0), -1);
rect.setSize(childSize);
rect.width = area.width;
rect.setLocation(area.x, area.y + area.height - rect.height);
bottom.setBounds(rect);
area.height -= rect.height + vGap;
}
if (left != null && left.isVisible()) {
childSize = left.getPreferredSize(-1, Math.max(0, area.height));
rect.setLocation(area.x, area.y);
rect.width = childSize.width;
rect.height = Math.max(0, area.height);
left.setBounds(rect);
area.x += rect.width + hGap;
area.width -= rect.width + hGap;
}
if (right != null && right.isVisible()) {
childSize = right.getPreferredSize(-1, Math.max(0, area.height));
rect.width = childSize.width;
rect.height = Math.max(0, area.height);
rect.setLocation(area.x + area.width - rect.width, area.y);
right.setBounds(rect);
area.width -= rect.width + hGap;
}
if (center != null && center.isVisible()) {
childSize = center.getPreferredSize(
Math.max(0, area.width),
Math.max(0, area.height));
if(!stretchCenterHeight){
if (childSize.height < area.height) {
area.y += (area.height - childSize.height) / 2;
area.height = childSize.height;
}
}
if(!stretchCenterWidth){
if (childSize.width < area.width) {
area.x += (area.width - childSize.width) / 2;
area.width = childSize.width;
}
}
center.setBounds(area);
}
}
/**
* @see org.eclipse.draw2d.AbstractLayout#remove(IFigure)
*/
public void remove(IFigure child) {
if (center == child) {
center = null;
} else if (top == child) {
top = null;
} else if (bottom == child) {
bottom = null;
} else if (right == child) {
right = null;
} else if (left == child) {
left = null;
}
}
/**
* Sets the location of hte given child in this layout. Valid constraints:
* <UL>
* <LI>{@link #CENTER}</LI>
* <LI>{@link #TOP}</LI>
* <LI>{@link #BOTTOM}</LI>
* <LI>{@link #LEFT}</LI>
* <LI>{@link #RIGHT}</LI>
* <LI><code>null</code> (to remove a child's constraint)</LI>
* </UL>
*
* <p>
* Ensure that the given Figure is indeed a child of the Figure on which this layout has
* been set. Proper behaviour cannot be guaranteed if that is not the case. Also ensure
* that every child has a valid constraint.
* </p>
* <p>
* Passing a <code>null</code> constraint will invoke {@link #remove(IFigure)}.
* </p>
* <p>
* If the given child was assigned another constraint earlier, it will be re-assigned to
* the new constraint. If there is another child with the given constraint, it will be
* over-ridden so that the given child now has that constraint.
* </p>
*
* @see org.eclipse.draw2d.AbstractLayout#setConstraint(IFigure, Object)
*/
public void setConstraint(IFigure child, Object constraint) {
remove(child);
super.setConstraint(child, constraint);
if (constraint == null) {
return;
}
switch (((Integer) constraint).intValue()) {
case PositionConstants.CENTER :
center = child;
break;
case PositionConstants.TOP :
top = child;
break;
case PositionConstants.BOTTOM :
bottom = child;
break;
case PositionConstants.RIGHT :
right = child;
break;
case PositionConstants.LEFT :
left = child;
break;
default :
break;
}
}
/**
* Sets the horizontal spacing to be used between the children. Default is 0.
*
* @param gap The horizonal spacing
*/
public void setHorizontalSpacing(int gap) {
hGap = gap;
}
/**
* Sets the vertical spacing ot be used between the children. Default is 0.
*
* @param gap The vertical spacing
*/
public void setVerticalSpacing(int gap) {
vGap = gap;
}
public boolean isStretchCenterHeight() {
return stretchCenterHeight;
}
public void setStretchCenterHeight(boolean stretchCenterHeight) {
this.stretchCenterHeight = stretchCenterHeight;
}
public boolean isStretchCenterWidth() {
return stretchCenterWidth;
}
public void setStretchCenterWidth(boolean stretchCenterWidth) {
this.stretchCenterWidth = stretchCenterWidth;
}
}
